[Zope-Checkins]
SVN: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/
Integrate Five 1.3b.
Philipp von Weitershausen
philikon at philikon.de
Wed Nov 2 12:17:43 EST 2005
Log message for revision 39847:
Integrate Five 1.3b.
Changed:
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/CHANGES.txt
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/CREDITS.txt
D Zope/branches/philikon-zope32-integration/lib/python/Products/Five/adding.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/TrustedExpression.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/__init__.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/absoluteurl.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/adding.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/configure.zcml
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/menu.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/meta.zcml
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/metaconfigure.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/resource.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/adding.txt
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/defaultview.zcml
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/overrides.zcml
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pages.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pages.txt
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pages.zcml
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pages_ftest.txt
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pts_test_languages.txt
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/resource.txt
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/resource_ftest.txt
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_absoluteurl.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_defaultview.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_i18n.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_menu.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_pages.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_recurse.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_resource.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_traversable.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/configure.zcml
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/deprecated.zcml
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/directives.txt
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/features.txt
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/five14goals.txt
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/localsite.txt
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/main.txt
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/__init__.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/addDemoContent.pt
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/browser.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/configure.zcml
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/democontent.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/green5.png
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/event.zcml
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/eventconfigure.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/fiveconfigure.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/fivedirectives.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/__init__.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/metaconfigure.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/objectwidget.pt
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/objectwidget.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/tests/configure.zcml
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/tests/forms.txt
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/tests/schemacontent.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/tests/test_forms.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/i18n.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/interfaces.py
D Zope/branches/philikon-zope32-integration/lib/python/Products/Five/interfaces.zcml
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/meta.zcml
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/metaconfigure.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/permissions.zcml
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/security.py
D Zope/branches/philikon-zope32-integration/lib/python/Products/Five/services.zcml
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/__init__.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/browser.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/configure.zcml
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/interfaces.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/localsite.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/managesite.pt
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/meta.zcml
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/metaconfigure.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/metadirectives.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/__init__.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/dummy.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/framework.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/functional.txt
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/sitemanager.txt
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_functional.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_localsite.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_sitemanager.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_utility.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/utility.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/skin/standardmacros.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/skin/tests/test_standardmacros.py
D Zope/branches/philikon-zope32-integration/lib/python/Products/Five/testing/
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/README.txt
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/boilerplate.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/directives.zcml
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/event.txt
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_directives.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_event.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_i18n.py
D Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_import_conflicts.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_registerclass.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_security.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_size.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_viewable.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/__init__.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/fancycontent.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/folder.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/restricted.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/simplecontent.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/traversable.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/__init__.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/__init__.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/configure.zcml
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/edit_markers.pt
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/manage_interfaces.pt
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/marker.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/tests/
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/tests/__init__.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/tests/framework.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/tests/test_marker.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/configure.zcml
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/interfaces.py
A Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/marker.py
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/version.txt
U Zope/branches/philikon-zope32-integration/lib/python/Products/Five/viewable.py
-=-
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/CHANGES.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/CHANGES.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/CHANGES.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -2,6 +2,95 @@
Five Changes
============
+Five 1.3b (2005-11-02)
+======================
+
+This version is also included in Zope 2.9b1.
+
+Restructuring
+-------------
+
+* Support for Zope 3.2 was added. Five now requires Zope 2.9 (which
+ ships with Zope 3.2).
+
+* As scheduled, the temporary fork of the new test runner
+ (``zope.testing``) at ``Five.testing`` was removed. So was the
+ ``runtests.py`` script. Use the regular Zope test runner
+ (``test.py`` or ``bin/zopectl test``) to run tests.
+
+* To reflect the Component Architecture simplification in Zope 3 since
+ the X3 3.0 release, ``IFiveUtilityService`` was renamed to
+ ``IFiveUtilityRegistry`` and ``SimpleLocalUtilityService`` was
+ renamed to ``SimpleLocalUtilityRegistry``. The old names are still
+ available for a short period of time.
+
+* Event support: ``<five:containerEvents/>`` is the default.
+
+* Due to an incompatability with Zope 3.2's ObjectWidget and Zope 2's
+ Page Templates, Five now ships with its own ObjectWidget
+ implementation (which is just a thin wrapper around Zope's one to
+ make it work in Zope 2). If you use the ObjectWidget, please change
+ your imports to ``Products.Five.form.objectwidget.ObjectWidget``.
+
+* Backwards compatability for Zope 3-style interfaces of Zope 2
+ components has been removed as that functionality is now in the Zope
+ 2 core as of Zope 2.9.
+
+Five 1.2b (2005-11-02)
+======================
+
+Features
+--------
+
+* Added IMarkerInterfaces adapter: This adapter provides methods for
+ inspecting and assigning marker interfaces. 'edit-markers.html' (or
+ 'manage_interfaces' in the ZMI) allows to change the behavior of specific
+ objects by adding or removing marker interfaces TTW.
+
+* Added the five:registerClass directive: This does the necessary Zope 2
+ registration for Five-based content. It is no longer necessary to add an
+ ``initialize()`` function to the product's __init__ in order to register
+ a meta type to be addable through the ZMI. See doc/products/ViewsTutorial
+ for an example how to use the directive.
+
+* Local site support: Five has now support for creating local sites
+ and thereby local utilities. This is mostly needed for allowing CMF
+ to convert it's portal tools into local utilities. See
+ doc/localsite.txt for more information
+
+* Event support: When ``<five:containerEvents/>`` is specified, Five
+ makes the standard Zope 2 containers send events instead of using
+ manage_afterAdd, manage_beforeDelete and manage_afterClone. These
+ methods are still called for a class declared
+ ``<five:deprecatedManageAddDelete class=.../>``, and are called in
+ compatibility mode with a deprecation warning for classes that don't
+ use this directive.
+
+Restructuring
+-------------
+
+* Removed backwards compatibility for Five 1.0 Zope core interfaces.
+
+* Removed backwards compatibility for Zope 2.7 and 2.8.0.
+
+* Added a (temporarily) forked copy of the "new-and-improved" test
+ runner and supporting 'zope.testing' package, lifted from
+ http://svn.zope.org/zope.testing. This code should be removed for
+ Five 1.3, which will use the updated version of 'zope.testing' in
+ the Zope 2.9 / Zope 3.2 tree.
+
+ There is a test runner invoking script in the ``Five`` package. For
+ example, to run the Five tests with the new test runner, simply
+ execute the following command line from your instance home::
+
+ $ bin/zopectl run Products/Five/runtests.py -v -s Products.Five
+
+* Moved the 'Five.testing' package down to 'Five.tests.testing', in
+ order to make room for the 'zope.testing' code.
+
+* Removed backwards compatibility for some moved classes (AddForm,
+ EditForm, ContentAdding)
+
Five 1.1 (2005-10-04)
=====================
@@ -100,7 +189,7 @@
* The former test product, ``FiveTest``, was converted into separate
modules that provide the mock objects for the corresponding tests
and are located right next to them. Common test helpers have been
- moved to the Five.testing package. Overall, the testing framework
+ moved to the Five.tests.testing package. Overall, the testing framework
was much simplified and the individual tests clean up after
themselves much like they do in Zope 3.
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/CREDITS.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/CREDITS.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/CREDITS.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -9,7 +9,7 @@
- Lennart Regebro (regebro at nuxeo.com)
-- Tres Seaver (tres at zope.com)
+- Tres Seaver (tseaver at palladion.com)
- Jan-Wijbrand Kolman (jw at infrae.com)
@@ -33,6 +33,9 @@
- Tarek Ziadé (tziade at nuxeo.com)
+- Whit Morriss (whit at longnow.org)
+
+
Thank you
---------
Deleted: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/adding.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/adding.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/adding.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -1,26 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004, 2005 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.
-#
-##############################################################################
-""" Z2 -> Z3 bridge utilities.
-
-$Id: adding.py 15515 2005-08-02 17:42:08Z yuppie $
-"""
-
-# BBB: This file will be removed in future versions of Five.
-from browser.adding import ContentAdding
-
-import warnings
-warnings.warn("\nThe Products.Five.adding module has been renamed to "
- "Products.Five.browser.adding \n"
- "and will be disabled starting in Five 1.2.\n",
- DeprecationWarning, stacklevel=2)
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/TrustedExpression.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/TrustedExpression.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/TrustedExpression.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -70,7 +70,7 @@
o = get(object, name, M)
if o is M:
try: o = object[name]
- except AttributeError: # better exception
+ except (AttributeError, TypeError): # better exception
raise AttributeError(name)
object = o
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/__init__.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/__init__.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/__init__.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -13,20 +13,13 @@
##############################################################################
"""Provide basic browser functionality
-$Id: __init__.py 18841 2005-10-23 09:57:38Z philikon $
+$Id: __init__.py 19283 2005-10-31 17:43:51Z philikon $
"""
import Acquisition
-from AccessControl import ClassSecurityInfo
-from Globals import InitializeClass
+import zope.app.publisher.browser
-class BrowserView(Acquisition.Explicit):
- security = ClassSecurityInfo()
+class BrowserView(Acquisition.Explicit, zope.app.publisher.browser.BrowserView):
+ """Five browser view
- def __init__(self, context, request):
- self.context = context
- self.request = request
-
- # XXX do not create any methods on the subclass called index_html,
- # as this makes Zope 2 traverse into that first!
-
-InitializeClass(BrowserView)
+ Mixes in explicit acquisition so that security can be acquired for
+ views"""
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/absoluteurl.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/absoluteurl.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/absoluteurl.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -52,7 +52,7 @@
return (
{'name': name, 'url': context.absolute_url()},)
- view = zapi.getViewProviding(container, IAbsoluteURL, request)
+ view = zapi.getMultiAdapter((container, request), IAbsoluteURL)
base = tuple(view.breadcrumbs())
base += (
{'name': name, 'url': ("%s/%s" % (base[-1]['url'], name))},)
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/adding.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/adding.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/adding.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -28,6 +28,8 @@
from zope.app.container.interfaces import IContainerNamesContainer
from zope.app.container.constraints import checkFactory, checkObject
+from zope.app.publisher.browser.menu import getMenu
+
from zope.app import zapi
from zope.app.event.objectevent import ObjectCreatedEvent
from zope.event import notify
@@ -84,8 +86,8 @@
# XXX this is definitely not right for all or even most uses
# of Five, but can be overridden by an AddView subclass, using
# the class attribute of a zcml:addform directive
- return (str(zapi.getView(self.context, "absolute_url", self.request))
- + '/manage_main')
+ return str(zapi.getMultiAdapter((self.context, self.request),
+ name=u"absolute_url")) + '/manage_main'
# set in BrowserView.__init__
request = None
@@ -104,7 +106,7 @@
if view_name.startswith('@@'):
view_name = view_name[2:]
- return zapi.getView(self, view_name, request)
+ return zapi.getMultiAdapter((self, request), name=view_name)
if name.startswith('@@'):
view_name = name[2:]
@@ -135,7 +137,7 @@
if zapi.queryView(self, view_name, self.request) is not None:
url = "%s/%s=%s" % (
- zapi.getView(self, "absolute_url", self.request),
+ zapi.getMultiAdapter((self, self.request), name=u"absolute_url"),
type_name, id)
self.request.response.redirect(url)
return
@@ -169,12 +171,11 @@
This is sorted by title.
"""
container = self.context
- menu_service = zapi.getService("BrowserMenu")
result = []
for menu_id in (self.menu_id, 'zope.app.container.add'):
if not menu_id:
continue
- for item in menu_service.getMenu(menu_id, self, self.request):
+ for item in getMenu(menu_id, self, self.request):
extra = item.get('extra')
if extra:
factory = extra.get('factory')
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/configure.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/configure.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/configure.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -1,17 +1,6 @@
<configure xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser">
- <serviceType
- id="BrowserMenu"
- interface="zope.app.publisher.interfaces.browser.IBrowserMenuService"
- />
-
- <service
- serviceType="BrowserMenu"
- permission="zope.Public"
- component="zope.app.publisher.browser.globalbrowsermenuservice.globalBrowserMenuService"
- />
-
<browser:defaultView name="index.html" />
<browser:page
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/menu.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/menu.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/menu.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -13,17 +13,15 @@
##############################################################################
"""Some menu code
-$Id: menu.py 14512 2005-07-11 18:40:51Z philikon $
+$Id: menu.py 19283 2005-10-31 17:43:51Z philikon $
"""
from zope.interface import implements
-from zope.app import zapi
from zope.app.publisher.interfaces.browser import IMenuAccessView
-from zope.app.servicenames import BrowserMenu
+from zope.app.publisher.browser.menu import getMenu
from Products.Five import BrowserView
class MenuAccessView(BrowserView):
implements(IMenuAccessView)
def __getitem__(self, menu_id):
- browser_menu_service = zapi.getService(BrowserMenu)
- return browser_menu_service.getMenu(menu_id, self.context, self.request)
+ return getMenu(menu_id, self.context, self.request)
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/meta.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/meta.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/meta.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -25,7 +25,7 @@
<meta:directive
name="defaultView"
schema="zope.app.publisher.browser.metadirectives.IDefaultViewDirective"
- handler=".metaconfigure.defaultView"
+ handler="zope.app.publisher.browser.metaconfigure.defaultView"
/>
<meta:directive
@@ -62,19 +62,19 @@
<meta:directive
name="menu"
schema="zope.app.publisher.browser.metadirectives.IMenuDirective"
- handler="zope.app.publisher.browser.globalbrowsermenuservice.menuDirective"
+ handler="zope.app.publisher.browser.menumeta.menuDirective"
/>
<meta:directive
name="menuItem"
schema="zope.app.publisher.browser.metadirectives.IMenuItemDirective"
- handler="zope.app.publisher.browser.globalbrowsermenuservice.menuItemDirective"
+ handler="zope.app.publisher.browser.menumeta.menuItemDirective"
/>
<meta:complexDirective
name="menuItems"
schema="zope.app.publisher.browser.metadirectives.IMenuItemsDirective"
- handler="zope.app.publisher.browser.globalbrowsermenuservice.menuItemsDirective"
+ handler="zope.app.publisher.browser.menumeta.menuItemsDirective"
>
<meta:subdirective
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/metaconfigure.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/metaconfigure.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/metaconfigure.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -21,18 +21,16 @@
import os
from zope.interface import Interface
-from zope.component import getGlobalService, ComponentLookupError
from zope.configuration.exceptions import ConfigurationError
-from zope.component.servicenames import Presentation
-from zope.publisher.interfaces.browser import IBrowserRequest
+from zope.publisher.interfaces.browser import IBrowserRequest, \
+ IDefaultBrowserLayer
+
from zope.app.publisher.browser.viewmeta import pages as zope_app_pages
from zope.app.publisher.browser.viewmeta import view as zope_app_view
-from zope.app.publisher.browser.viewmeta import providesCallable
-from zope.app.publisher.browser.globalbrowsermenuservice import\
- menuItemDirective
+from zope.app.publisher.browser.viewmeta import providesCallable, \
+ _handle_menu, _handle_for
from zope.app.component.metaconfigure import handler
from zope.app.component.interface import provideInterface
-from zope.app.container.interfaces import IAdding
from Products.Five.browser import BrowserView
from Products.Five.browser.resource import FileResourceFactory, ImageResourceFactory
@@ -40,22 +38,16 @@
from Products.Five.browser.resource import DirectoryResourceFactory
from Products.Five.browser.pagetemplatefile import ZopeTwoPageTemplateFile
from Products.Five.metaclass import makeClass
-from Products.Five.security import getSecurityInfo, protectClass, \
- protectName, initializeClass
+from Products.Five.security import getSecurityInfo, protectClass, protectName
-import ExtensionClass
+from Globals import InitializeClass as initializeClass
def page(_context, name, permission, for_,
- layer='default', template=None, class_=None,
+ layer=IDefaultBrowserLayer, template=None, class_=None,
allowed_interface=None, allowed_attributes=None,
attribute='__call__', menu=None, title=None,
):
- try:
- s = getGlobalService(Presentation)
- except ComponentLookupError, err:
- pass
-
_handle_menu(_context, menu, title, [for_], name, permission)
if not (class_ or template):
@@ -64,8 +56,7 @@
allowed_attributes = []
if allowed_interface is not None:
for interface in allowed_interface:
- attrs = [n for n, d in interface.namesAndDescriptions(1)]
- allowed_attributes.extend(attrs)
+ allowed_attributes.extend(interface.names())
if attribute != '__call__':
if template:
@@ -92,9 +83,10 @@
"The provided class doesn't have the specified attribute "
)
cdict = getSecurityInfo(class_)
+ cdict['__name__'] = name
if template:
new_class = makeClassForTemplate(template, bases=(class_, ),
- cdict=cdict)
+ cdict=cdict, name=name)
elif attribute != "__call__":
# we're supposed to make a page for an attribute (read:
# method) and it's not __call__. We thus need to create a
@@ -125,16 +117,15 @@
else:
# template
- new_class = makeClassForTemplate(template)
+ new_class = makeClassForTemplate(template, name=name)
_handle_for(_context, for_)
_context.action(
discriminator = ('view', for_, name, IBrowserRequest, layer),
callable = handler,
- args = (Presentation, 'provideAdapter',
- IBrowserRequest, new_class, name, [for_], Interface, layer,
- _context.info),
+ args = ('provideAdapter',
+ (for_, layer), Interface, name, new_class, _context.info),
)
_context.action(
discriminator = ('five:protectClass', new_class),
@@ -165,19 +156,6 @@
menu=menu, title=title,
**(self.opts))
-def defaultView(_context, name, for_=None):
-
- type = IBrowserRequest
-
- _context.action(
- discriminator = ('defaultViewName', for_, type, name),
- callable = handler,
- args = (Presentation,
- 'setDefaultViewName', for_, type, name),
- )
-
- _handle_for(_context, for_)
-
# view (named view with pages)
class view(zope_app_view):
@@ -192,11 +170,6 @@
pages = {}
for pname, attribute, template in self.pages:
- try:
- s = getGlobalService(Presentation)
- except ComponentLookupError, err:
- pass
-
if template:
cdict[pname] = ZopeTwoPageTemplateFile(template)
if attribute and attribute != name:
@@ -255,7 +228,7 @@
if class_ is not None:
bases = (class_, ViewMixinForTemplates)
else:
- bases = (ViewMixinForTemplates)
+ bases = (ViewMixinForTemplates,)
try:
cname = str(name)
@@ -277,37 +250,11 @@
discriminator = ('view', for_, name, IBrowserRequest, layer,
self.provides),
callable = handler,
- args = (Presentation, 'provideAdapter',
- IBrowserRequest, newclass, name, [for_], self.provides,
- layer, _context.info),
+ args = ('provideAdapter',
+ (for_, layer), self.provides, name, newclass,
+ _context.info),
)
-def _handle_for(_context, for_):
- if for_ is not None:
- _context.action(
- discriminator = None,
- callable = provideInterface,
- args = ('', for_)
- )
-
-def _handle_menu(_context, menu, title, for_, name, permission):
- if menu or title:
- if not (menu and title):
- raise ConfigurationError(
- "If either menu or title are specified, they must "
- "both be specified.")
-
- if len(for_) != 1:
- raise ConfigurationError(
- "Menus can be specified only for single-view, not for "
- "multi-views.")
-
- return menuItemDirective(
- _context, menu, for_[0], '@@' + str(name), title,
- permission=permission)
-
- return []
-
_factory_map = {'image':{'prefix':'ImageResource',
'count':0,
'factory':ImageResourceFactory},
@@ -319,7 +266,7 @@
'factory':PageTemplateResourceFactory}
}
-def resource(_context, name, layer='default', permission='zope.Public',
+def resource(_context, name, layer=IDefaultBrowserLayer, permission='zope.Public',
file=None, image=None, template=None):
if ((file and image) or (file and template) or
@@ -343,8 +290,8 @@
_context.action(
discriminator = ('resource', name, IBrowserRequest, layer),
callable = handler,
- args = (Presentation, 'provideResource',
- name, IBrowserRequest, factory, layer),
+ args = ('provideAdapter',
+ (layer,), Interface, name, factory, _context.info),
)
_context.action(
discriminator = ('five:protectClass', new_class),
@@ -367,7 +314,7 @@
'count':0}
}
-def resourceDirectory(_context, name, directory, layer='default',
+def resourceDirectory(_context, name, directory, layer=IDefaultBrowserLayer,
permission='zope.Public'):
if not os.path.isdir(directory):
@@ -410,8 +357,8 @@
_context.action(
discriminator = ('resource', name, IBrowserRequest, layer),
callable = handler,
- args = (Presentation, 'provideResource',
- name, IBrowserRequest, factory, layer),
+ args = ('provideAdapter',
+ (layer,), Interface, name, factory, _context.info),
)
for new_class in new_classes:
_context.action(
@@ -456,11 +403,12 @@
return self.index(self, *args, **kw)
def makeClassForTemplate(filename, globals=None, used_for=None,
- bases=(), cdict=None):
+ bases=(), cdict=None, name=u''):
# XXX needs to deal with security from the bases?
if cdict is None:
cdict = {}
- cdict.update({'index': ZopeTwoPageTemplateFile(filename, globals)})
+ cdict.update({'index': ZopeTwoPageTemplateFile(filename, globals),
+ '__name__': name})
bases += (ViewMixinForTemplates,)
class_ = makeClass("SimpleViewClass from %s" % filename, bases, cdict)
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/resource.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/resource.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/resource.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -18,15 +18,15 @@
import os
import urllib
-from Acquisition import Explicit
+import Acquisition
from ComputedAttribute import ComputedAttribute
from OFS.Traversable import Traversable as OFSTraversable
-from zope.exceptions import NotFoundError
from zope.interface import implements
from zope.component.interfaces import IResource
-from zope.component import getViewProviding
from zope.publisher.interfaces.browser import IBrowserPublisher
+
+from zope.app import zapi
from zope.app.traversing.browser.interfaces import IAbsoluteURL
from zope.app.datetimeutils import time as timeFromDateTimeString
from zope.app.publisher.fileresource import File, Image
@@ -37,7 +37,7 @@
_marker = []
-class Resource(Explicit):
+class Resource(Acquisition.Explicit):
"""A publishable resource
"""
implements(IResource)
@@ -49,7 +49,9 @@
name = self.__name__
container = self.__parent__
- url = str(getViewProviding(container, IAbsoluteURL, self.request))
+ # TODO Zope 3 uses site = getSite() instead of container here
+ # and the @@ resource access view
+ url = str(zapi.getMultiAdapter((container, self.request), IAbsoluteURL))
url = urllib.unquote(url)
if not isinstance(container, DirectoryResource):
name = '++resource++%s' % name
@@ -213,7 +215,7 @@
filename = os.path.join(path, name)
if not os.path.isfile(filename):
if default is _marker:
- raise NotFoundError(name)
+ raise KeyError(name)
return default
ext = name.split('.')[-1]
factory = self.resource_factories.get(ext, self.default_factory)
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/adding.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/adding.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/adding.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -7,7 +7,7 @@
First we need to import and setup some prerequisites:
- >>> from Products.Five.testing import manage_addFiveTraversableFolder
+ >>> from Products.Five.tests.testing import manage_addFiveTraversableFolder
>>> from Products.Five.browser.adding import ObjectManagerNameChooser
>>> manage_addFiveTraversableFolder(self.folder, 'testoid', 'Testoid')
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/defaultview.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/defaultview.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/defaultview.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -3,15 +3,15 @@
xmlns:five="http://namespaces.zope.org/five">
<five:defaultViewable
- class="Products.Five.testing.simplecontent.SimpleContent" />
+ class="Products.Five.tests.testing.simplecontent.SimpleContent" />
<browser:defaultView
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
name="eagledefaultview.txt"
/>
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
name="eagledefaultview.txt"
class=".pages.SimpleView"
attribute="eagle"
@@ -22,16 +22,16 @@
already provides __call__, such as our CallableSimpleContent -->
<five:defaultViewable
- class="Products.Five.testing.simplecontent.CallableSimpleContent" />
+ class="Products.Five.tests.testing.simplecontent.CallableSimpleContent" />
<!-- this tests whether five:defaultViewable can be called on a class that
already provides index_html, such as our IndexSimpleContent -->
<five:defaultViewable
- class="Products.Five.testing.simplecontent.IndexSimpleContent" />
+ class="Products.Five.tests.testing.simplecontent.IndexSimpleContent" />
<browser:defaultView
- for="Products.Five.testing.simplecontent.IIndexSimpleContent"
+ for="Products.Five.tests.testing.simplecontent.IIndexSimpleContent"
name="index_html"
/>
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/overrides.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/overrides.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/overrides.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -3,11 +3,11 @@
<!-- mouse instead of eagle -->
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
class=".pages.SimpleView"
attribute="mouse"
name="overridden_view"
permission="zope2.Public"
/>
-</configure>
\ No newline at end of file
+</configure>
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pages.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pages.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pages.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -34,6 +34,11 @@
def view(self):
return "Fancy, fancy"
+class CallView(BrowserView):
+
+ def __call__(self):
+ return "I was __call__()'ed"
+
class CallableNoDocstring:
def __call__(self):
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pages.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pages.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pages.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -10,7 +10,7 @@
Let's add a test object that we view most of the pages off of:
- >>> from Products.Five.testing.simplecontent import manage_addSimpleContent
+ >>> from Products.Five.tests.testing.simplecontent import manage_addSimpleContent
>>> manage_addSimpleContent(self.folder, 'testoid', 'Testoid')
We also need to create a stub user account and login; otherwise we
@@ -29,7 +29,7 @@
A browser page that is a view class's attribute (method):
>>> view = self.folder.unrestrictedTraverse('testoid/eagle.txt')
- >>> view != None
+ >>> view is not None
True
>>> from Products.Five.browser.tests.pages import SimpleView
>>> isinstance(view, SimpleView)
@@ -196,8 +196,10 @@
>>> from Products.Five.traversable import FakeRequest
>>> from zope.app import zapi
+ >>> from zope.app.publication.browser import setDefaultSkin
>>> request = FakeRequest()
- >>> view = zapi.getView(self.folder.testoid, 'eagle.txt', request)
+ >>> setDefaultSkin(request)
+ >>> view = zapi.getMultiAdapter((self.folder.testoid, request), name=u'eagle.txt')
It's protecting the object with the permission, and not the attribute,
so we get ('',) instead of ('eagle',):
@@ -213,7 +215,7 @@
>>> view_roles
('Manager',)
-Check to see if view's context properly acquires it's true
+Check to see if view's context properly acquires its true
parent
>>> from Acquisition import aq_parent, aq_base, aq_inner
@@ -255,8 +257,8 @@
... 'nodoc-method', 'nodoc-function', 'nodoc-object',
... 'dirpage1', 'dirpage2']
- >>> from Products.Five.testing.restricted import checkRestricted
- >>> from Products.Five.testing.restricted import checkUnauthorized
+ >>> from Products.Five.tests.testing.restricted import checkRestricted
+ >>> from Products.Five.tests.testing.restricted import checkUnauthorized
As long as we're not authenticated, we should get Unauthorized for
protected views, but we should be able to view the public ones:
@@ -312,5 +314,5 @@
Clean up
--------
- >>> from zope.app.tests.placelesssetup import tearDown
+ >>> from zope.app.testing.placelesssetup import tearDown
>>> tearDown()
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pages.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pages.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pages.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -8,7 +8,7 @@
<!-- attribute page -->
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
class=".pages.SimpleView"
attribute="eagle"
name="eagle.txt"
@@ -16,7 +16,7 @@
/>
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
class=".pages.SimpleView"
name="eagle.method"
permission="zope2.ViewManagementScreens"
@@ -25,7 +25,7 @@
<!-- attribute page -->
<browser:pages
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
class=".pages.SimpleView"
permission="zope2.ViewManagementScreens"
>
@@ -41,7 +41,7 @@
<!-- template/class page -->
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
class=".pages.SimpleView"
template="falcon.pt"
name="falcon.html"
@@ -50,7 +50,7 @@
<!-- template page (with simple python expression) -->
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
template="owl.pt"
name="owl.html"
permission="zope2.ViewManagementScreens"
@@ -59,7 +59,7 @@
<!-- template page which calls on context using python and path
expressions -->
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
template="flamingo.pt"
name="flamingo.html"
permission="zope2.ViewManagementScreens"
@@ -67,7 +67,7 @@
<!-- template/class page which calls on context, view, views -->
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
class=".pages.SimpleView"
template="condor.pt"
name="condor.html"
@@ -76,7 +76,7 @@
<!-- template page that defines a macro page -->
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
template="birdmacro.pt"
name="bird.html"
permission="zope2.ViewManagementScreens"
@@ -84,7 +84,7 @@
<!-- template page that uses macro page -->
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
template="seagull.pt"
name="seagull.html"
permission="zope2.ViewManagementScreens"
@@ -92,21 +92,21 @@
<!-- test TALES -->
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
template="ostrich.pt"
name="ostrich.html"
permission="zope2.ViewManagementScreens"
/>
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
template="tales_traversal.pt"
name="tales_traversal.html"
permission="zope2.ViewManagementScreens"
/>
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
template="template_variables.pt"
name="template_variables.html"
permission="zope2.ViewManagementScreens"
@@ -115,7 +115,7 @@
<!-- template security -->
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
template="security.pt"
name="security.html"
permission="zope2.View"
@@ -124,7 +124,7 @@
<!-- a publicly accessible page, attribute, template, template/class -->
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
class=".pages.SimpleView"
attribute="eagle"
name="public_attribute_page"
@@ -132,14 +132,14 @@
/>
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
template="owl.pt"
name="public_template_page"
permission="zope2.Public"
/>
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
class=".pages.SimpleView"
template="falcon.pt"
name="public_template_class_page"
@@ -147,16 +147,23 @@
/>
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
class=".pages.SimpleView"
template="parakeet.pt"
name="parakeet.html"
permission="zope2.ViewManagementScreens"
/>
+ <browser:page
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
+ class=".pages.CallView"
+ name="callview.html"
+ permission="zope2.Public"
+ />
+
<!-- pages from methods/functions/callables that don't have docstrings -->
<browser:pages
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
class="Products.Five.browser.tests.pages.NoDocstringView"
permission="zope2.Public">
<browser:page
@@ -177,7 +184,7 @@
This is mainly used to load Zope2 skin templates so they can be used
in five skins and layers. -->
<five:pagesFromDirectory
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
module="Products.Five.browser.tests"
directory="pages"
permission="zope2.Public"
@@ -186,7 +193,7 @@
<!-- browser:page directives with new style classes are ignored -->
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
class=".pages.NewStyleClass"
name="new_style_class"
attribute="method"
@@ -198,7 +205,7 @@
<browser:view
name=""
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
class=".pages.SimpleView"
permission="zope2.Public"
/>
@@ -207,18 +214,18 @@
<!-- protected edit form for permission check -->
<browser:editform
- schema="Products.Five.testing.simplecontent.ISimpleContent"
+ schema="Products.Five.tests.testing.simplecontent.ISimpleContent"
name="protectededitform.html"
permission="zope2.ViewManagementScreens"
/>
<!-- stuff that we'll override in overrides.zcml -->
<browser:page
- for="Products.Five.testing.simplecontent.ISimpleContent"
+ for="Products.Five.tests.testing.simplecontent.ISimpleContent"
class=".pages.SimpleView"
attribute="eagle"
name="overridden_view"
permission="zope2.Public"
/>
-</configure>
\ No newline at end of file
+</configure>
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pages_ftest.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pages_ftest.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pages_ftest.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -11,7 +11,7 @@
Let's also add one of our stub objects to play with:
- >>> from Products.Five.testing.simplecontent import manage_addSimpleContent
+ >>> from Products.Five.tests.testing.simplecontent import manage_addSimpleContent
>>> manage_addSimpleContent(self.folder, 'testoid', 'Testoid')
@@ -122,8 +122,23 @@
... self.failUnless(status == 200, (status, 200, view_name))
+Miscellaneous
+-------------
+
+Zope 2 always wants objects in the traversal graph to have a __name__.
+That is also true for views, e.g. a view constructed from a simple
+class bearing only a __call__ method:
+
+ >>> print http(r'''
+ ... GET /test_folder_1_/testoid/callview.html HTTP/1.1
+ ... ''')
+ HTTP/1.1 200 OK
+ ...
+ I was __call__()'ed
+
+
Clean up
--------
- >>> from zope.app.tests.placelesssetup import tearDown
+ >>> from zope.app.testing.placelesssetup import tearDown
>>> tearDown()
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pts_test_languages.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pts_test_languages.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/pts_test_languages.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -42,7 +42,7 @@
Finally, we need a traversable folder so that the test page we
registered is found:
- >>> from Products.Five.testing import manage_addFiveTraversableFolder
+ >>> from Products.Five.tests.testing import manage_addFiveTraversableFolder
>>> manage_addFiveTraversableFolder(self.folder, 'ftf')
Now for some actual testing... Our test page is a simple ZPT
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/resource.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/resource.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/resource.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -8,7 +8,7 @@
>>> zcml.load_config("configure.zcml", Products.Five)
>>> zcml.load_config('resource.zcml', package=Products.Five.browser.tests)
- >>> from Products.Five.testing import manage_addFiveTraversableFolder
+ >>> from Products.Five.tests.testing import manage_addFiveTraversableFolder
>>> manage_addFiveTraversableFolder(self.folder, 'testoid', 'Testoid')
>>> import os, glob
@@ -73,8 +73,8 @@
Security
--------
- >>> from Products.Five.testing.restricted import checkRestricted
- >>> from Products.Five.testing.restricted import checkUnauthorized
+ >>> from Products.Five.tests.testing.restricted import checkRestricted
+ >>> from Products.Five.tests.testing.restricted import checkUnauthorized
>>> resource_names = ['cockatiel.html', 'style.css', 'pattern.png']
@@ -112,5 +112,5 @@
Clean up
--------
- >>> from zope.app.tests.placelesssetup import tearDown
+ >>> from zope.app.testing.placelesssetup import tearDown
>>> tearDown()
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/resource_ftest.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/resource_ftest.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/resource_ftest.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -8,7 +8,7 @@
>>> zcml.load_config("configure.zcml", Products.Five)
>>> zcml.load_config('resource.zcml', package=Products.Five.browser.tests)
- >>> from Products.Five.testing import manage_addFiveTraversableFolder
+ >>> from Products.Five.tests.testing import manage_addFiveTraversableFolder
>>> manage_addFiveTraversableFolder(self.folder, 'testoid', 'Testoid')
>>> import os, glob
@@ -69,5 +69,5 @@
Clean up
--------
- >>> from zope.app.tests.placelesssetup import tearDown
+ >>> from zope.app.testing.placelesssetup import tearDown
>>> tearDown()
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_absoluteurl.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_absoluteurl.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_absoluteurl.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -29,7 +29,7 @@
>>> from Products.Five import zcml
>>> zcml.load_config("configure.zcml", Products.Five)
- >>> from Products.Five.testing import manage_addFiveTraversableFolder
+ >>> from Products.Five.tests.testing import manage_addFiveTraversableFolder
>>> manage_addFiveTraversableFolder(self.folder, 'testoid', 'Testoid')
A simple traversal will yield us the @@absolute_url view:
@@ -86,7 +86,7 @@
Clean up:
- >>> from zope.app.tests.placelesssetup import tearDown
+ >>> from zope.app.testing.placelesssetup import tearDown
>>> tearDown()
"""
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_defaultview.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_defaultview.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_defaultview.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -33,9 +33,9 @@
Now let's add a couple of stub objects:
- >>> from Products.Five.testing.simplecontent import manage_addSimpleContent
- >>> from Products.Five.testing.simplecontent import manage_addCallableSimpleContent
- >>> from Products.Five.testing.simplecontent import manage_addIndexSimpleContent
+ >>> from Products.Five.tests.testing.simplecontent import manage_addSimpleContent
+ >>> from Products.Five.tests.testing.simplecontent import manage_addCallableSimpleContent
+ >>> from Products.Five.tests.testing.simplecontent import manage_addIndexSimpleContent
>>> manage_addSimpleContent(self.folder, 'testoid', 'Testoid')
>>> manage_addCallableSimpleContent(self.folder, 'testcall', 'TestCall')
@@ -79,7 +79,7 @@
Clean up:
- >>> from zope.app.tests.placelesssetup import tearDown
+ >>> from zope.app.testing.placelesssetup import tearDown
>>> tearDown()
"""
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_i18n.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_i18n.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_i18n.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -33,7 +33,7 @@
... </configure>
... <configure package="Products.Five.browser.tests">
... <browser:page
- ... for="Products.Five.interfaces.IFolder"
+ ... for="OFS.interfaces.IFolder"
... template="i18n.pt"
... name="i18n.html"
... permission="zope2.View"
@@ -49,7 +49,7 @@
In order to be able to traverse to the PageTemplate view, we need
a traversable object:
- >>> from Products.Five.testing import manage_addFiveTraversableFolder
+ >>> from Products.Five.tests.testing import manage_addFiveTraversableFolder
>>> manage_addFiveTraversableFolder(self.folder, 'testoid', 'Testoid')
We tell Zope to translate the messages by passing the
@@ -80,7 +80,7 @@
Clean up:
- >>> from zope.app.tests.placelesssetup import tearDown
+ >>> from zope.app.testing.placelesssetup import tearDown
>>> tearDown()
"""
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_menu.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_menu.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_menu.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -28,7 +28,8 @@
>>> import Products.Five.browser.tests
>>> from Products.Five import zcml
- >>> zcml.load_config("configure.zcml", Products.Five)
+ >>> zcml.load_config("meta.zcml", Products.Five)
+ >>> zcml.load_config("permissions.zcml", Products.Five)
>>> zcml.load_config('menu.zcml', package=Products.Five.browser.tests)
>>> from Products.Five.security import newInteraction
@@ -37,12 +38,12 @@
Now for some actual testing... Let's look up the menu we registered:
>>> from Products.Five.traversable import FakeRequest
- >>> from zope.app.publisher.browser.globalbrowsermenuservice import \\
- ... globalBrowserMenuService
+ >>> from zope.app.publication.browser import setDefaultSkin
+ >>> from zope.app.publisher.browser.menu import getMenu
>>> request = FakeRequest()
- >>> menu = globalBrowserMenuService.getMenu(
- ... 'testmenu', self.folder, request)
+ >>> setDefaultSkin(request)
+ >>> menu = getMenu('testmenu', self.folder, request)
It should have
@@ -53,28 +54,42 @@
>>> menu.sort(lambda x, y: cmp(x['title'], y['title']))
>>> from pprint import pprint
- >>> pprint(menu)
- [{'action': '@@cockatiel_menu_public.html',
- 'description': '',
- 'extra': None,
- 'selected': '',
- 'title': u'Page in a menu (public)'},
- {'action': u'seagull.html',
- 'description': u'This is a test menu item',
- 'extra': None,
- 'selected': '',
- 'title': u'Test Menu Item'},
- {'action': u'parakeet.html',
- 'description': u'This is a test menu item',
- 'extra': None,
- 'selected': '',
- 'title': u'Test Menu Item 2'},
- {'action': u'falcon.html',
- 'description': u'This is a test menu item',
- 'extra': None,
- 'selected': '',
- 'title': u'Test Menu Item 3'}]
+ >>> pprint(menu[0])
+ {'action': u'@@cockatiel_menu_public.html',
+ 'description': u'',
+ 'extra': None,
+ 'icon': None,
+ 'selected': u'',
+ 'submenu': None,
+ 'title': u'Page in a menu (public)'}
+ >>> pprint(menu[1])
+ {'action': u'seagull.html',
+ 'description': u'This is a test menu item',
+ 'extra': None,
+ 'icon': None,
+ 'selected': u'',
+ 'submenu': None,
+ 'title': u'Test Menu Item'}
+
+ >>> pprint(menu[2])
+ {'action': u'parakeet.html',
+ 'description': u'This is a test menu item',
+ 'extra': None,
+ 'icon': None,
+ 'selected': u'',
+ 'submenu': None,
+ 'title': u'Test Menu Item 2'}
+
+ >>> pprint(menu[3])
+ {'action': u'falcon.html',
+ 'description': u'This is a test menu item',
+ 'extra': None,
+ 'icon': None,
+ 'selected': u'',
+ 'submenu': None,
+ 'title': u'Test Menu Item 3'}
+
Let's create a manager user account and log in.
>>> uf = self.folder.acl_users
@@ -82,8 +97,7 @@
>>> self.login('manager')
>>> newInteraction()
- >>> menu = globalBrowserMenuService.getMenu(
- ... 'testmenu', self.folder, request)
+ >>> menu = getMenu('testmenu', self.folder, request)
We should get the protected menu items now:
@@ -91,47 +105,73 @@
7
>>> menu.sort(lambda x, y: cmp(x['title'], y['title']))
- >>> pprint(menu)
- [{'action': '@@cockatiel_menu_protected.html',
- 'description': '',
- 'extra': None,
- 'selected': '',
- 'title': u'Page in a menu (protected)'},
- {'action': '@@cockatiel_menu_public.html',
- 'description': '',
+ >>> pprint(menu[0])
+ {'action': u'@@cockatiel_menu_protected.html',
+ 'description': u'',
'extra': None,
- 'selected': '',
- 'title': u'Page in a menu (public)'},
+ 'icon': None,
+ 'selected': u'',
+ 'submenu': None,
+ 'title': u'Page in a menu (protected)'}
+
+ >>> pprint(menu[1])
+ {'action': u'@@cockatiel_menu_public.html',
+ 'description': u'',
+ 'extra': None,
+ 'icon': None,
+ 'selected': u'',
+ 'submenu': None,
+ 'title': u'Page in a menu (public)'}
+
+ >>> pprint(menu[2])
{'action': u'seagull.html',
'description': u'This is a protected test menu item',
'extra': None,
- 'selected': '',
- 'title': u'Protected Test Menu Item'},
+ 'icon': None,
+ 'selected': u'',
+ 'submenu': None,
+ 'title': u'Protected Test Menu Item'}
+
+ >>> pprint(menu[3])
{'action': u'falcon.html',
'description': u'This is a protected test menu item',
'extra': None,
- 'selected': '',
- 'title': u'Protected Test Menu Item 2'},
+ 'icon': None,
+ 'selected': u'',
+ 'submenu': None,
+ 'title': u'Protected Test Menu Item 2'}
+
+ >>> pprint(menu[4])
{'action': u'seagull.html',
'description': u'This is a test menu item',
'extra': None,
- 'selected': '',
- 'title': u'Test Menu Item'},
+ 'icon': None,
+ 'selected': u'',
+ 'submenu': None,
+ 'title': u'Test Menu Item'}
+
+ >>> pprint(menu[5])
{'action': u'parakeet.html',
'description': u'This is a test menu item',
'extra': None,
- 'selected': '',
- 'title': u'Test Menu Item 2'},
+ 'icon': None,
+ 'selected': u'',
+ 'submenu': None,
+ 'title': u'Test Menu Item 2'}
+
+ >>> pprint(menu[6])
{'action': u'falcon.html',
'description': u'This is a test menu item',
'extra': None,
- 'selected': '',
- 'title': u'Test Menu Item 3'}]
+ 'icon': None,
+ 'selected': u'',
+ 'submenu': None,
+ 'title': u'Test Menu Item 3'}
Clean up:
- >>> from zope.app.tests.placelesssetup import tearDown
+ >>> from zope.app.testing.placelesssetup import tearDown
>>> tearDown()
"""
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_pages.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_pages.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_pages.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -26,7 +26,7 @@
>>> zcml.load_config("configure.zcml", Products.Five)
>>> zcml.load_config('pages.zcml', package=Products.Five.browser.tests)
- >>> from Products.Five.testing.simplecontent import manage_addSimpleContent
+ >>> from Products.Five.tests.testing.simplecontent import manage_addSimpleContent
>>> manage_addSimpleContent(self.folder, 'testoid', 'Testoid')
>>> uf = self.folder.acl_users
>>> uf._doAddUser('manager', 'r00t', ['Manager'], [])
@@ -56,7 +56,7 @@
Clean up:
- >>> from zope.app.tests.placelesssetup import tearDown
+ >>> from zope.app.testing.placelesssetup import tearDown
>>> tearDown()
"""
@@ -65,11 +65,10 @@
from Testing.ZopeTestCase import installProduct, ZopeDocTestSuite
from Testing.ZopeTestCase import ZopeDocFileSuite
from Testing.ZopeTestCase import FunctionalDocFileSuite
- installProduct('PythonScripts') # for Five.testing.restricted
+ installProduct('PythonScripts') # for Five.tests.testing.restricted
return unittest.TestSuite((
ZopeDocTestSuite(),
- ZopeDocFileSuite('pages.txt',
- package='Products.Five.browser.tests'),
+ ZopeDocFileSuite('pages.txt', package='Products.Five.browser.tests'),
FunctionalDocFileSuite('pages_ftest.txt',
package='Products.Five.browser.tests')
))
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_recurse.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_recurse.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_recurse.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -23,9 +23,6 @@
"""
Test recursion
- >>> from zope.app.tests.placelesssetup import setUp, tearDown
- >>> setUp()
-
This test makes sure that recursion is avoided for view lookup.
First, we need to set up a stub interface...
@@ -51,10 +48,10 @@
>>> from Products.Five.fiveconfigure import classDefaultViewable
>>> classDefaultViewable(Recurse)
- >>> from zope.app import zapi
+ >>> from zope.component import provideAdapter
>>> from zope.publisher.interfaces.browser import IBrowserRequest
- >>> pres = zapi.getGlobalService('Presentation')
- >>> pres.setDefaultViewName(IRecurse, IBrowserRequest, 'view')
+ >>> from zope.component.interfaces import IDefaultViewName
+ >>> provideAdapter(u'view', (IRecurse, IBrowserRequest), IDefaultViewName)
Here comes the actual test:
@@ -65,9 +62,10 @@
'foo'
- Clean up:
+ Clean up adapter registry and monkey patches to classes:
- >>> tearDown()
+ >>> from zope.testing.cleanup import cleanUp
+ >>> cleanUp()
"""
def test_suite():
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_resource.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_resource.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_resource.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -23,7 +23,7 @@
import unittest
from Testing.ZopeTestCase import installProduct, ZopeDocFileSuite
from Testing.ZopeTestCase import FunctionalDocFileSuite
- installProduct('PythonScripts') # for Five.testing.restricted
+ installProduct('PythonScripts') # for Five.tests.testing.restricted
return unittest.TestSuite((
ZopeDocFileSuite('resource.txt',
package='Products.Five.browser.tests'),
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_traversable.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_traversable.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/browser/tests/test_traversable.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -33,7 +33,7 @@
the wrong reason: None doesn't have a docstring so BaseRequest
raises NotFoundError.)
- >>> from Products.Five.testing.simplecontent import manage_addSimpleContent
+ >>> from Products.Five.tests.testing.simplecontent import manage_addSimpleContent
>>> manage_addSimpleContent(self.folder, 'testoid', 'Testoid')
>>> print http(r'''
... GET /test_folder_1_/testoid/doesntexist HTTP/1.1
@@ -54,21 +54,21 @@
... <meta:redefinePermission from="zope2.Public" to="zope.Public" />
...
... <five:traversable
- ... class="Products.Five.testing.fancycontent.FancyContent"
+ ... class="Products.Five.tests.testing.fancycontent.FancyContent"
... />
...
... <browser:page
- ... for="Products.Five.testing.fancycontent.IFancyContent"
+ ... for="Products.Five.tests.testing.fancycontent.IFancyContent"
... class="Products.Five.browser.tests.pages.FancyView"
... attribute="view"
- ... name="fancy"
+ ... name="fancyview"
... permission="zope2.Public"
... />
...
... </configure>'''
>>> zcml.load_string(configure_zcml)
- >>> from Products.Five.testing.fancycontent import manage_addFancyContent
+ >>> from Products.Five.tests.testing.fancycontent import manage_addFancyContent
>>> info = manage_addFancyContent(self.folder, 'fancy', '')
In the following test we let the original __bobo_traverse__ method
@@ -85,7 +85,7 @@
actually works:
>>> print http(r'''
- ... GET /test_folder_1_/fancy/fancy HTTP/1.1
+ ... GET /test_folder_1_/fancy/fancyview HTTP/1.1
... ''')
HTTP/1.1 200 OK
...
@@ -94,7 +94,7 @@
Clean up:
- >>> from zope.app.tests.placelesssetup import tearDown
+ >>> from zope.app.testing.placelesssetup import tearDown
>>> tearDown()
"""
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/configure.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/configure.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/configure.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -2,13 +2,15 @@
xmlns:five="http://namespaces.zope.org/five">
<include file="meta.zcml" />
- <include file="services.zcml" />
- <include file="interfaces.zcml" />
<include file="permissions.zcml" />
<include file="i18n.zcml" />
+ <include file="event.zcml"/>
+ <include file="deprecated.zcml"/>
+ <include package=".site" />
<include package=".browser" />
<include package=".form" />
<include package=".skin" />
+ <include package=".utilities" />
<include package="zope.app.event" />
<include package="zope.app.traversing" />
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/deprecated.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/deprecated.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/deprecated.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,51 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+ xmlns:five="http://namespaces.zope.org/five">
+
+ <!-- deprecated in core Zope, should be fixed there in Zope 2.9 -->
+
+ <five:deprecatedManageAddDelete
+ class="AccessControl.User.BasicUserFolder"/>
+
+ <five:deprecatedManageAddDelete
+ class="App.Factory.Factory"/>
+ <five:deprecatedManageAddDelete
+ class="App.Permission.Permission"/>
+
+ <five:deprecatedManageAddDelete
+ class="HelpSys.HelpTopic.HelpTopicBase"/>
+
+ <five:deprecatedManageAddDelete
+ class="OFS.Cache.CacheManager"/>
+
+ <five:deprecatedManageAddDelete
+ class="Products.OFSP.Draft.Draft"/>
+ <five:deprecatedManageAddDelete
+ class="Products.OFSP.Version.Version"/>
+
+ <five:deprecatedManageAddDelete
+ class="Products.PythonScripts.PythonScript.PythonScript"/>
+
+ <five:deprecatedManageAddDelete
+ class="Products.Sessions.BrowserIdManager.BrowserIdManager"/>
+ <five:deprecatedManageAddDelete
+ class="Products.Sessions.SessionDataManager.SessionDataManager"/>
+
+ <five:deprecatedManageAddDelete
+ class="Products.SiteAccess.VirtualHostMonster.VirtualHostMonster"/>
+ <five:deprecatedManageAddDelete
+ class="Products.SiteAccess.SiteRoot.Traverser"/>
+
+ <five:deprecatedManageAddDelete
+ class="Products.SiteErrorLog.SiteErrorLog.SiteErrorLog"/>
+
+ <five:deprecatedManageAddDelete
+ class="Products.ZCatalog.CatalogAwareness.CatalogAware"/>
+ <five:deprecatedManageAddDelete
+ class="Products.ZCatalog.CatalogPathAwareness.CatalogAware"/>
+
+ <five:deprecatedManageAddDelete
+ class="ZClasses.Property.ZCommonSheet"/>
+ <five:deprecatedManageAddDelete
+ class="ZClasses.ZClass.ZClass"/>
+
+</configure>
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/deprecated.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/directives.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/directives.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/directives.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -33,16 +33,6 @@
Redefine a permission in included ZCML as another one.
-service
--------
-
-Declare a global service
-
-serviceType
------------
-
-Declare a type of service.
-
skin
----
@@ -55,9 +45,25 @@
interface
---------
+
Register an interface in ZCML.
+factory
+-------
+Register an object factory.
+
+modulealias
+-----------
+
+Provide a module under an alias name, e.g. for persistent backward
+compatability.
+
+hook
+----
+
+Install a hook on a hookable object.
+
browser ``http://namespaces.zope.org/browser``
==============================================
@@ -148,16 +154,34 @@
Retrieve size information for a Zope 2 content class via a Zope 3
style ``ISized`` adapter.
-sendEvents
-----------
+containerEvents
+---------------
-Lets a Zope 2 content class send out Zope 3 object events that
-correspond to the Zope 2 methods ``manage_afterAdd`` and
-``manage_beforeDelete``.
+Make events be sent for Zope 2 container objects, instead of calling old
+methods like ``manage_afterAdd``. These old methods will still be called
+for classes specified in a ``deprecatedManageAddDelete`` directive.
+deprecatedManageAddDelete
+-------------------------
+
+Specify a class that needs its old deprecated methods like
+``manage_afterAdd``, ``manage_beforeDelete`` and ``manage_afterClone``
+to be called. Modern classes should use event subscribers instead.
+
pagesFromDirectory
------------------
-Load all *.pt files in a directory as pages. Useful when you want to
-share templates between Five and CMF, so you can declare pages like
-this is a similar way to setting up skin folders in portal_skins.
+Loads all files with .pt extension in a directory as pages.
+
+registerClass
+-------------
+
+Registers Five content with Zope 2.
+
+localsite
+---------
+
+Turns a class into an implementation of ``IPossibleSite`` so that its
+instances can be serve as local sites. Unless otherwise specified, a
+default implementation's methods will be used to make the class comply
+with the ``IPossibleSite`` interface.
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/features.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/features.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/features.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -8,7 +8,7 @@
Zope 3 interfaces
=================
-Everything in the ``zope.interface`` package should work. Zope 3
+Everything from the ``zope.interface`` package works. Zope 3
interfaces are the foundation of the component architecture, and also
the foundation of schemas.
@@ -84,3 +84,18 @@
ignored by views anyway, as they are trusted -- it only serves to
protect directly exposed methods on content classes (the python
scripts and the ZPublisher).
+
+Local Sites
+===========
+
+Five supports the concept of a local sites and local site managers.
+See localsite.txt_ for more information.
+
+.. _localsite.txt: localsite.html
+
+Object events
+=============
+
+Five supports sending Zope 3 object events when objects are added,
+moved, renamed, copied and deleted. The use of ``manage_afterAdd`` & co
+methods is deprecated.
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/five14goals.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/five14goals.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/five14goals.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,107 @@
+===============================
+Porting Five to Zope 3.1+ notes
+===============================
+
+Introduction
+------------
+
+Five needs to work in Zope 2.9. Zope 2.9 will ship with Zope 3.2. This
+means Five will need to work with Zope 3.2. Since Zope 3.2 doesn't
+truly exist yet we'll target Zope 3.1 for now.
+
+A Five Roadmap
+--------------
+
+Here is a tentative Five roadmap:
+
+Five 1.1 is to be released shortly, and its main feature is a
+refactored directory structure and Zope 3 i18n for Zope 2. It's still
+targeting the Zope X3.0 that's in Zope 2.8.
+
+Five 1.2 is still targetting Zope 2.8, and its main expected feature
+is support for local utilities.
+
+Five 1.3 is targetting Zope 2.9 and thus Zope 3.2. We're talking about
+this release of Five in this document.
+
+Main problem
+------------
+
+Zope 3.1 has internal changes that Five needs to support. Five works
+by reimplementing ZCML statements it supplies in the context of Zope
+2. This reimplementation is hard to maintain, as for each Zope 3
+upgrade we need to review all these ZCML statements and port them into
+Five again.
+
+The straightforward way to start supporting Zope 3.1+ with Five would
+be to review all the ZCML statements in Five and update them to work
+with Zope 3.1+.
+
+A more ambitious but nicer solution would be if we could reuse the
+Zope 3 ZCML statements directly. If we could accomplish this,
+maintainability of Five would be improved by a lot. Far less review of
+Five would be necessary for each Zope 3 upgrade. In the rest of this
+document we'll be discussing this scenario.
+
+Reasons for Five's modified ZCML statements
+-------------------------------------------
+
+Five ships with modified implementations of Zope 3 ZCML statements for
+a number of reasons:
+
+* could not use new-style classes that are in Zope 3 due to
+ ExtensionClass.
+
+* Five views need to work with the Zope 2 publisher, and this expects
+ different things than the Zope 3 publisher.
+
+* cannot use the Zope 3 security system, while the Zope 3 ZCML calls
+ into this to configure it.
+
+* Five views need to work with the Zope 2 security system. This means
+ Five needs to issue Zope 2 style security declarations for views.
+
+We'll go into more detail about each of these points below.
+
+New-style ExtensionClass
+========================
+
+Five needed to be compatible with Zope 2.7, which uses old-style
+ExtensionClass. This made life difficult for Five, as Zope 3 uses
+new-style Python classes in many places. It's not easy to mix the two.
+
+Zope 2.8 changed to allow new-style ExtensionClasses, which are
+compatible with new-style Python classes. This means Five can
+hopefully be simplified as we can forget about old-style
+ExtensionClasses.
+
+Five views need to work with the Zope 2 publisher
+=================================================
+
+The Zope 2 publisher expects something quite different than the Zope 3
+publisher.
+
+* does what is returned to the publisher need to inherit from
+ Acquisition.Explicit? (security reasons?)
+
+* we may need something that calls the right methods on the Zope 3
+ view (such as browserDefault, __call__ and publishTraverse)
+
+Cannot use the Zope 3 security system
+=====================================
+
+Do the Zope 3 security calls get in the way? Five currently removes
+these calls, but perhaps doing the calls does not harm.
+
+If they do interface, we could perhaps still trick things into
+working harmlessly.
+
+Five must issue Zope 2 security declarations for views
+======================================================
+
+This cannot be done by the ZCML implementation of Zope 3. We could
+hopefully do this by following the following pattern::
+
+ def our_directive_implementation(...):
+ original_directive_implementation(...)
+ do_the_zope2_work(...)
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/five14goals.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/localsite.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/localsite.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/localsite.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,126 @@
+Local sites in Five
+===================
+
+Intro
+-----
+
+Zope 3 has a concept of local sites and site managers. They allow one
+to locally override component registrations and have components and
+their configuration be persisted in the ZODB as well as managed
+through the web interface.
+
+By default, Zope 3 has a global site which is configured through ZCML.
+It provides the fallback for all component look-up. Local sites are
+typically set during traversal, when the traverser encounters an
+``ISite`` object. The last encountered ``ISite`` wins. Component
+look-up will cascade through all the sites in the hierarchy and fall
+back to the global site where it can finally fail.
+
+Five also supports local sites, however by default only local
+utilities. Local adapters, such as ZODB-based views, could be
+supported with a custom implementation of the local site manager and
+local adapter registry. This is not the focus of local sites in Five,
+though.
+
+
+Turning possible sites into sites
+---------------------------------
+
+Five uses the same technique as Zope 3 for determining local sites:
+sites are found during URL traversal. However, since the Zope 2
+ZPublisher doesn't emit the necessary events by default, Five needs to
+set a ``BeforeTraverse`` hook on site objects.
+
+Setting this hook needs to be done an object-per-object basis and can
+be performed through the ``manage_site.html`` browser page. This view
+operates on ``IPossibleSite`` objects (in other words, objects that
+*can* be sites but aren't yet). It sets the traversal hook on the
+object and then marks it with the ``ISite`` interface to indicate that
+it is a real site now, not just a possible site.
+
+Note that unlike the Zope 3 equivalent of this view, it does not set
+the site manager to site; it is assumed that the site already knows
+how to get its site manager.
+
+Also note that in order for the view to work, the object's class needs
+to be Five-traversable, e.g. with the following ZCML statement:
+
+ <five:traversable class=".module.MyClass" />
+
+
+Custom site implementations
+---------------------------
+
+Anything can be a site, there are no restrictions (sites don't have to
+be folders, for examples). Sites can also be nested. For all the
+Component Architecture cares, every object in your URL graph could be
+a site.
+
+The only requirement are two interfaces:
+
+``IPossibleSite``
+
+ Objects that can potentially be turned into a site need to provide
+ this interface. That requires them to have a ``setSiteManager()``
+ and ``getSiteManager()`` method for setting and getting the local
+ site manager of that site. The site manager is the registry that
+ takes care of local component look-up.
+
+``IFiveSiteManager``
+
+ This interface is a slight extension of the ``IServiceService`` or
+ ``ISiteManager`` interface, respectively (the former in Zope X3
+ 3.0, the latter in later versions). It defines the API of a local
+ site manager that is to be used in a Five environment. The site's
+ ``getSiteManager()`` method should return an object providing this
+ interface.
+
+
+Five's default site manager
+----------------------------
+
+If you want to instantly make your custom class an ``IPossibleSite``
+implementation, you can use a default mix-in class from Five, e.g.::
+
+ class MySite(OFS.Folder, Products.Five.site.localsite.FiveSite):
+ pass
+
+This default implementation of ``IPossibleSite`` features a site
+manager implementation that knows how to register and look-up local
+utilities. It does so by adapting the site to
+``IFiveUtilityRegistry``.
+
+The default adapter for this local utility registry simply stores the
+utilities in a standard OFS Folder on called ``utilities`` on the site
+object. You probably want to exchange that simple behaviour with
+something that works better in your application. You can do so by
+plugging in your own utility registry adapter, e.g.::
+
+ <adapter for=".interfaces.IMySite"
+ provides="Products.Five.site.interfaces.IFiveUtilityRegistry"
+ fatory=".module.MyUtilityRegistry" />
+
+All this implementation needs to do is comply with the
+``IFiveUtilityRegistry`` interface, which essentially means the
+standard utility look-up methods like ``queryUtility()``,
+``getUtilitiesFor()``, etc.
+
+
+Turning existing classes into possible sites
+--------------------------------------------
+
+If you cannot or do not want to modify existing classes to mix in the
+``FiveSite`` class, you can also use a structured monkey patch via
+ZCML::
+
+ <five:localsite class=".module.MyClass" />
+
+This makes ``MyClass`` an ``IPossibleSite`` and sticks ``FiveSite``'s
+``getSiteManager()`` and ``setSiteManager()`` methods on the class as
+well. You can also tell it to use a different site implementation's
+methods for the monkey patch::
+
+ <five:localsite class=".module.MyClass"
+ site_class=".module.MySiteImpl" />
+
+Just make sure that this class implements ``IPossibleSite``.
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/localsite.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/main.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/main.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/main.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -5,33 +5,42 @@
-------------
Five is a Zope 2 product that allows you to integrate Zope 3
-technologies into Zope 2, today. Five right now allows you to use the
-following Zope 3 technologies in Zope 2:
+technologies into Zope 2, today. Among others, it allows you to use
+Zope 3 interfaces, ZCML-based configuration, adapters, browser pages
+(including skins, layers, and resources), automated add and edit forms
+based on schemas, object events, as well as Zope 3-style i18n message
+catalogs.
-* Zope 3 interfaces
+We've tried to keep the Five experience as close to Zope 3 as
+possible, so this means that what you learn while using Five should
+also be applicable to Zope 3, and viceversa.
-* adapters
+Five 1.0 and 1.1 work on a straight Zope 2.7 installation, as long as
+Zope 3 has been installed. Five 1.2 requires Zope 2.8 which already
+ships with Zope 3, Five 1.3 is included in Zope 2.9.
-* pages (views), including skins and layers, and edit and add forms
-
-* ZCML
-
-It is possible to add Zope 3 style views to your own Zope 2 objects,
-or to existing ones, even normal Folders!
-
-Five works with a straight Zope 2.7 installation, as long as Zope 3
-has been installed. See Five's INSTALL.txt for more information on how
-to set it up.
-
We're in the process of evaluating lots more Zope 3 technologies for
-integration into Zope 2. This is the right moment for interested Zope
-2 and Zope 3 developers to jump in. We're looking for cooperation
+integration into Zope 2. This is the right moment for interested Zope
+2 and Zope 3 developers to jump in. We're looking for cooperation
between different Zope 2 projects so that this can be a foundational
system for us all.
Download
--------
+2005-11-02 -- We have released Five 1.2b and 1.3b! Download Five 1.2b
+here:
+
+http://codespeak.net/z3/five/release/Five-1.2b.tgz
+
+2005-10-04 -- We have released Five 1.1! Download it here:
+
+http://codespeak.net/z3/five/release/Five-1.1.tgz
+
+2005-07-13 -- We have released Five 1.1b! Download it here:
+
+http://codespeak.net/z3/five/release/Five-1.1b.tgz
+
2005-07-12 -- We have released Five 1.0.2! This is also the version
that will be included in Zope 2.8.1. Download it here:
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/__init__.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/__init__.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/__init__.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -1,22 +1 @@
-##############################################################################
-#
-# Copyright (c) 2005 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.
-#
-##############################################################################
-
-import democontent
-
-def initialize(context):
-
- context.registerClass(
- democontent.DemoContent,
- constructors = (democontent.manage_addDemoContentForm,
- democontent.manage_addDemoContent),
- )
+# make this directory a package
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/addDemoContent.pt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/addDemoContent.pt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/addDemoContent.pt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,46 @@
+<h1 tal:replace="structure context/manage_page_header">Header</h1>
+
+<h2 tal:define="form_title string:Add Demo Content"
+ tal:replace="structure context/manage_form_title">Form Title</h2>
+
+<p class="form-help">
+Add Demo Content
+</p>
+
+<form action="." method="post"
+ tal:attributes="action request/ACTUAL_URL">
+<table cellspacing="0" cellpadding="2" border="0">
+ <tr>
+ <td align="left" valign="top">
+ <div class="form-label">
+ Id
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <input type="text" name="add_input_name" size="40" />
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ <div class="form-label">
+ Title
+ </div>
+ </td>
+ <td align="left" valign="top">
+ <input type="text" name="title" size="40" />
+ </td>
+ </tr>
+ <tr>
+ <td align="left" valign="top">
+ </td>
+ <td align="left" valign="top">
+ <div class="form-element">
+ <input class="form-element" type="submit" name="submit_add"
+ value=" Add " />
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+
+<h1 tal:replace="structure context/manage_page_footer">Footer</h1>
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/addDemoContent.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/browser.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/browser.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/browser.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -1,20 +1,12 @@
-##############################################################################
-#
-# Copyright (c) 2005 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.
-#
-##############################################################################
-
-from Products.Five import BrowserView
import random
+from democontent import DemoContent
-class Overview(BrowserView):
+
+class Overview:
+
+ """View for overview.
+ """
+
def reversedIds(self):
result = []
for id in self.context.objectIds():
@@ -27,9 +19,28 @@
def directlyPublished(self):
return "This is directly published"
-class NewExample(BrowserView):
+
+class NewExample:
+
+ """View for new example.
+ """
+
def helpsWithOne(self):
return random.randrange(10)
-
+
def two(self):
return "Two got called"
+
+
+class DemoContentAddView:
+
+ """Add view for demo content.
+ """
+
+ def __call__(self, add_input_name='', title='', submit_add=''):
+ if submit_add:
+ obj = DemoContent(add_input_name, title)
+ self.context.add(obj)
+ self.request.response.redirect(self.context.nextURL())
+ return ''
+ return self.index()
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/configure.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/configure.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/configure.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -1,37 +1,39 @@
-<configure
- xmlns="http://namespaces.zope.org/zope"
- xmlns:browser="http://namespaces.zope.org/browser"
- xmlns:five="http://namespaces.zope.org/five">
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:browser="http://namespaces.zope.org/browser"
+ xmlns:five="http://namespaces.zope.org/five">
- <five:traversable
- class="OFS.Folder.Folder"
- />
+ <five:traversable class="OFS.Application.Application"/>
+ <!-- OFS.Folder.Folder views -->
+
+ <five:traversable class="OFS.Folder.Folder"/>
+
<browser:page
- for="Products.Five.interfaces.IFolder"
- name="overview.html"
- template="overview.pt"
- permission="zope2.ViewManagementScreens"
- />
-
+ for="OFS.interfaces.IFolder"
+ name="overview.html"
+ template="overview.pt"
+ permission="zope2.ViewManagementScreens"
+ />
+
<browser:page
- for="Products.Five.interfaces.IFolder"
- name="overview2.html"
- template="overview2.pt"
- permission="zope2.ViewManagementScreens"
- class=".browser.Overview"
- />
+ for="OFS.interfaces.IFolder"
+ name="overview2.html"
+ template="overview2.pt"
+ class=".browser.Overview"
+ permission="zope2.ViewManagementScreens"
+ />
<browser:page
- for="Products.Five.interfaces.IFolder"
- name="test.html"
- class=".browser.Overview"
- attribute="directlyPublished"
- permission="zope2.ViewManagementScreens"
- />
+ for="OFS.interfaces.IFolder"
+ name="test.html"
+ class=".browser.Overview"
+ attribute="directlyPublished"
+ permission="zope2.ViewManagementScreens"
+ />
<browser:pages
- for="Products.Five.interfaces.IFolder"
+ for="OFS.interfaces.IFolder"
class=".browser.NewExample"
permission="zope2.ViewManagementScreens"
>
@@ -45,19 +47,43 @@
/>
</browser:pages>
- <five:traversable class=".democontent.DemoContent" />
+ <!-- .democontent.IDemoContent views -->
+ <five:traversable class=".democontent.DemoContent"/>
+
<browser:page
- for=".democontent.IDemoContent"
- name="someview.html"
- template="someview.pt"
- permission="zope2.ViewManagementScreens"
- />
+ for="zope.app.container.interfaces.IAdding"
+ name="addDemoContent.html"
+ template="addDemoContent.pt"
+ class=".browser.DemoContentAddView"
+ permission="zope2.ViewManagementScreens"
+ />
- <five:defaultViewable class=".democontent.DemoContent" />
-
+ <browser:resource
+ name="green5.png"
+ image="green5.png"
+ />
+
+ <five:registerClass
+ class=".democontent.DemoContent"
+ meta_type="Five Demo Content"
+ addview="addDemoContent.html"
+ icon="green5.png"
+ permission="zope2.ViewManagementScreens"
+ />
+
+ <browser:page
+ for=".democontent.IDemoContent"
+ name="someview.html"
+ template="someview.pt"
+ permission="zope2.ViewManagementScreens"
+ />
+
+ <five:defaultViewable class=".democontent.DemoContent"/>
+
<browser:defaultView
- for=".democontent.IDemoContent"
- name="someview.html" />
+ for=".democontent.IDemoContent"
+ name="someview.html"
+ />
</configure>
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/democontent.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/democontent.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/democontent.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -1,44 +1,21 @@
-##############################################################################
-#
-# Copyright (c) 2005 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.
-#
-##############################################################################
-
from zope.interface import Interface, implements
from OFS.SimpleItem import SimpleItem
-from Products.PageTemplates.PageTemplateFile import PageTemplateFile
+
class IDemoContent(Interface):
+
def mymethod():
- "Return some text"
-
+ """Return some text.
+ """
+
+
class DemoContent(SimpleItem):
+
implements(IDemoContent)
- meta_type = 'Five Demo Content'
-
def __init__(self, id, title):
self.id = id
self.title = title
def mymethod(self):
return "Hello world"
-
-
-manage_addDemoContentForm = PageTemplateFile(
- "www/demoContentAdd", globals(),
- __name__ = 'manage_addDemoContentForm')
-
-def manage_addDemoContent(self, id, title, REQUEST=None):
- """Add the demo content."""
- id = self._setObject(id, DemoContent(id, title))
- if REQUEST is None:
- return
- REQUEST.RESPONSE.redirect(REQUEST['URL1'] + '/manage_main')
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/green5.png
===================================================================
(Binary files differ)
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/doc/products/ViewsTutorial/green5.png
___________________________________________________________________
Name: svn:mime-type
+ image/png
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/event.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/event.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/event.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,36 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+
+ <!-- Adapter giving sublocations for ObjectManagers, used
+ by dispatchToSublocations -->
+
+ <adapter
+ for="OFS.interfaces.IObjectManager"
+ provides="zope.app.location.interfaces.ISublocations"
+ factory="OFS.subscribers.ObjectManagerSublocations"
+ />
+
+ <!-- dispatch IObjectWillBeMovedEvent with "bottom-up" semantics -->
+
+ <subscriber
+ for="OFS.interfaces.IItem
+ OFS.interfaces.IObjectWillBeMovedEvent"
+ handler="OFS.subscribers.dispatchObjectWillBeMovedEvent"
+ />
+
+ <!-- dispatch IObjectMovedEvent with "top-down" semantics -->
+
+ <subscriber
+ for="OFS.interfaces.IItem
+ zope.app.container.interfaces.IObjectMovedEvent"
+ handler="OFS.subscribers.dispatchObjectMovedEvent"
+ />
+
+ <!-- dispatch IObjectClonedEvent with "top-down" semantics -->
+
+ <subscriber
+ for="OFS.interfaces.IItem
+ OFS.interfaces.IObjectClonedEvent"
+ handler="OFS.subscribers.dispatchObjectClonedEvent"
+ />
+
+</configure>
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/event.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/eventconfigure.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/eventconfigure.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/eventconfigure.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -1,6 +1,6 @@
##############################################################################
#
-# Copyright (c) 2004, 2005 Zope Corporation and Contributors.
+# Copyright (c) 2005 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
@@ -15,109 +15,38 @@
Use 'structured monkey patching' to enable zope.app.container event sending for
Zope 2 objects.
-$Id: eventconfigure.py 17810 2005-09-24 09:12:59Z efge $
+$Id: eventconfigure.py 19413 2005-11-02 14:37:52Z efge $
"""
-from Products.Five.fiveconfigure import isFiveMethod
-from zope.event import notify
-from zope.interface import implements
-from zope.app.container.interfaces import IObjectAddedEvent,\
- IObjectRemovedEvent
-from zope.app.container.contained import ObjectMovedEvent
-from zope.app.event.objectevent import ObjectCopiedEvent
-# holds classes that were monkeyed with; for clean up
-_monkied = []
+import warnings
+from OFS.subscribers import deprecatedManageAddDeleteClasses
-# ObjectAddedEvent and ObjectRemovedEvent are different in Zope 2
-class ObjectAddedEvent(ObjectMovedEvent):
- implements(IObjectAddedEvent)
+def setContainerEvents():
+ warnings.warn("Using <five:containerEvents/> is deprecated (it is now "
+ "the default), it will be removed in Zope 2.11",
+ DeprecationWarning)
- def __init__(self, object, newParent=None, newName=None):
- if newParent is None:
- newParent = object.aq_inner.aq_parent
- if newName is None:
- newName = object.id
- ObjectMovedEvent.__init__(self, object, None, None, newParent, newName)
-
-class ObjectRemovedEvent(ObjectMovedEvent):
- implements(IObjectRemovedEvent)
+def setDeprecatedManageAddDelete(class_):
+ """Instances of the class will still see their old methods called."""
+ deprecatedManageAddDeleteClasses.append(class_)
- def __init__(self, object, oldParent=None, oldName=None):
- if oldParent is None:
- oldParent = object.aq_inner.aq_parent
- if oldName is None:
- oldName = object.id
- ObjectMovedEvent.__init__(self, object, oldParent, oldName, None, None)
-
-def manage_afterAdd(self, item, container):
- original_location_path = getattr(self, '__five_location_path__', None)
- self.__five_location_path__ = self.getPhysicalPath()
- # if there still is an object in the original location, we're copied
- # we cannot rely on manage_afterClone, as this gets triggered only
- # *after* a manage_afterAdd. This logic might fail in the case where
- # something *is* somehow left in the original location that can
- # be traversed to.
- is_copied = original_location_path and (self.unrestrictedTraverse(
- original_location_path, None) is not None)
- if is_copied:
- notify(ObjectCopiedEvent(self))
- if original_location_path is None or is_copied:
- notify(ObjectAddedEvent(self))
- else:
- original_location = self.unrestrictedTraverse(
- original_location_path[:-1])
- notify(ObjectMovedEvent(self,
- original_location, original_location_path[-1],
- container, self.id))
- # call original
- method = getattr(self, '__five_original_manage_afterAdd', None)
- if method is not None:
- self.__five_original_manage_afterAdd(item, container)
+def cleanUp():
+ deprecatedManageAddDeleteClasses[:] = []
-manage_afterAdd.__five_method__ = True
+def containerEvents(_context):
+ _context.action(
+ discriminator=None,
+ callable=setContainerEvents,
+ args=(),
+ )
-def manage_beforeDelete(self, item, container):
- notify(ObjectRemovedEvent(self))
- # call original
- method = getattr(self, '__five_original_manage_beforeDelete', None)
- if method is not None:
- self.__five_original_manage_beforeDelete(item, container)
-
-manage_beforeDelete.__five_method__ = True
-
-def classSendEvents(class_):
- """Make instances of the class send Object*Event."""
- # tuck away original methods if necessary
- for name in ['manage_afterAdd', 'manage_beforeDelete']:
- method = getattr(class_, name, None)
- if not isFiveMethod(method):
- # if we haven't alread overridden this, tuck away originals
- setattr(class_, '__five_original_' + name, method)
-
- class_.manage_afterAdd = manage_afterAdd
- class_.manage_beforeDelete = manage_beforeDelete
- # remember class for clean up
- _monkied.append(class_)
-
-def sendEvents(_context, class_):
+def deprecatedManageAddDelete(_context, class_):
_context.action(
- discriminator = ('five:sendEvents', class_),
- callable = classSendEvents,
- args=(class_,)
+ discriminator=('five:deprecatedManageAddDelete', class_),
+ callable=setDeprecatedManageAddDelete,
+ args=(class_,),
)
-# clean up code
-from Products.Five.fiveconfigure import killMonkey
from zope.testing.cleanup import addCleanUp
-
-def unsendEvents(class_):
- """Restore class's initial state with respect to sending events"""
- for name in ['manage_afterAdd', 'manage_beforeDelete']:
- killMonkey(class_, name, '__five_original_'+name)
-
-def cleanUp():
- for class_ in _monkied:
- unsendEvents(class_)
-
addCleanUp(cleanUp)
del addCleanUp
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/fiveconfigure.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/fiveconfigure.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/fiveconfigure.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -22,12 +22,20 @@
import glob
import warnings
-import App
+import App.config
+import Products
from zLOG import LOG, ERROR
-from zope.interface import classImplements
+from zope.interface import classImplements, classImplementsOnly, implementedBy
+from zope.interface.interface import InterfaceClass
from zope.configuration import xmlconfig
+from zope.configuration.exceptions import ConfigurationError
+from zope.publisher.interfaces.browser import IDefaultBrowserLayer
+
+from zope.app import zapi
from zope.app.component.interface import provideInterface
+from zope.app.component.metaconfigure import adapter
+from zope.app.security.interfaces import IPermission
from viewable import Viewable
from traversable import Traversable
@@ -55,7 +63,7 @@
# in the control panel. However, all attempts to do so has failed from my
# side. //regebro
exc = sys.exc_info()
- LOG('Five', ERROR, 'Could not import Product %s' % name, error=exc)
+ LOG('Five', ERROR, 'Could not import Product %s' % product.__name__, error=exc)
def loadProducts(_context):
products = findProducts()
@@ -177,20 +185,6 @@
args = (class_,)
)
-def viewable(_context, class_):
- # XXX do not need to mark where this is used, as simple search
- # should find all instances easily
- warnings.warn(
- 'The five:viewable directive has been deprecated. '
- 'Please use the five:traversable directive instead.',
- DeprecationWarning)
-
- _context.action(
- discriminator = None,
- callable = classTraversable,
- args=(class_,)
- )
-
def createZope2Bridge(zope2, package, name):
# Map a Zope 2 interface into a Zope3 interface, seated within 'package'
# as 'name'.
@@ -215,7 +209,7 @@
)
def pagesFromDirectory(_context, directory, module, for_=None,
- layer='default', permission='zope.Public'):
+ layer=IDefaultBrowserLayer, permission='zope.Public'):
if isinstance(module, basestring):
module = _context.resolve(module)
@@ -233,6 +227,41 @@
page(_context, name=name, permission=permission,
layer=layer, for_=for_, template=fname)
+
+_register_monkies = []
+_meta_type_regs = []
+def _registerClass(class_, meta_type, permission, addview, icon, global_):
+ setattr(class_, 'meta_type', meta_type)
+
+ permission_obj = zapi.getUtility(IPermission, permission)
+
+ if icon:
+ setattr(class_, 'icon', '++resource++%s' % icon)
+
+ interfaces = tuple(implementedBy(class_))
+
+ info = {'name': meta_type,
+ 'action': addview and ('+/%s' % addview) or '',
+ 'product': 'Five',
+ 'permission': str(permission_obj.title),
+ 'visibility': global_ and 'Global' or None,
+ 'interfaces': interfaces,
+ 'instance': class_,
+ 'container_filter': None}
+
+ Products.meta_types += (info,)
+
+ _register_monkies.append(class_)
+ _meta_type_regs.append(meta_type)
+
+def registerClass(_context, class_, meta_type, permission, addview=None,
+ icon=None, global_=True):
+ _context.action(
+ discriminator = ('registerClass', meta_type),
+ callable = _registerClass,
+ args = (class_, meta_type, permission, addview, icon, global_)
+ )
+
# clean up code
def killMonkey(class_, name, fallback, attr=None):
@@ -265,12 +294,34 @@
killMonkey(class_, '__browser_default__', '__fallback_default__',
'__five_viewable__')
+def unregisterClass(class_):
+ delattr(class_, 'meta_type')
+ try:
+ delattr(class_, 'icon')
+ except AttributeError:
+ pass
+
def cleanUp():
+ global _traversable_monkies
for class_ in _traversable_monkies:
untraversable(class_)
+ _traversable_monkies = []
+
+ global _defaultviewable_monkies
for class_ in _defaultviewable_monkies:
undefaultViewable(class_)
+ _defaultviewable_monkies = []
+ global _register_monkies
+ for class_ in _register_monkies:
+ unregisterClass(class_)
+ _register_monkies = []
+
+ global _meta_type_regs
+ Products.meta_types = tuple([ info for info in Products.meta_types
+ if info['name'] not in _meta_type_regs ])
+ _meta_type_regs = []
+
from zope.testing.cleanup import addCleanUp
addCleanUp(cleanUp)
del addCleanUp
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/fivedirectives.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/fivedirectives.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/fivedirectives.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -17,7 +17,10 @@
"""
from zope.interface import Interface
from zope.app.publisher.browser.metadirectives import IBasicResourceInformation
+from zope.app.security.fields import Permission
from zope.configuration.fields import GlobalObject, Tokens, PythonIdentifier
+from zope.configuration.fields import Bool
+from zope.schema import ASCII
from zope.schema import TextLine
class IImplementsDirective(Interface):
@@ -56,7 +59,7 @@
required=True
)
-class ISendEventsDirective(Interface):
+class ISizableDirective(Interface):
"""Make instances of class send events.
"""
@@ -65,6 +68,19 @@
required=True
)
+class IContainerEventsDirective(Interface):
+ """Global switch to enable container events
+ """
+
+class IDeprecatedManageAddDeleteDirective(Interface):
+ """Call manage_afterAdd & co for these contained content classes.
+ """
+ class_ = GlobalObject(
+ title=u"Class",
+ required=True,
+ )
+
+
class IBridgeDirective(Interface):
"""Bridge from a Zope 2 interface to an equivalent Zope3 interface.
"""
@@ -104,3 +120,51 @@
description=u"The directory containing the resource data.",
required=True
)
+
+class IRegisterClassDirective(Interface):
+
+ """registerClass directive schema.
+
+ Register Five content with Zope 2.
+ """
+
+ class_ = GlobalObject(
+ title=u'Instance Class',
+ description=u'Dotted name of the class that is registered.',
+ required=True
+ )
+
+ meta_type = ASCII(
+ title=u'Meta Type',
+ description=u'A human readable unique identifier for the class.',
+ required=True
+ )
+
+ permission = Permission(
+ title=u'Add Permission',
+ description=u'The permission for adding objects of this class.',
+ required=True
+ )
+
+ addview = ASCII(
+ title=u'Add View ID',
+ description=u'The ID of the add view used in the ZMI. Consider this '
+ u'required unless you know exactly what you do.',
+ default=None,
+ required=False
+ )
+
+ icon = ASCII(
+ title=u'Icon ID',
+ description=u'The ID of the icon used in the ZMI.',
+ default=None,
+ required=False
+ )
+
+ global_ = Bool(
+ title=u'Global scope?',
+ description=u'If "global" is False the class is only available in '
+ u'containers that explicitly allow one of its interfaces.',
+ default=True,
+ required=False
+ )
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/__init__.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/__init__.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/__init__.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -33,7 +33,7 @@
from zope.app.form.utility import setUpWidgets, getWidgetsData
from zope.app.form.interfaces import IInputWidget, WidgetsError
from zope.app.event.objectevent import ObjectCreatedEvent, ObjectModifiedEvent
-from zope.app.i18n import ZopeMessageIDFactory as _
+from zope.app.i18n import ZopeMessageFactory as _
from Products.Five.browser import BrowserView
from Products.Five.browser.pagetemplatefile import ZopeTwoPageTemplateFile
@@ -144,12 +144,13 @@
if changed:
self.changed()
# XXX: Needs locale support:
- # formatter = self.request.locale.dates.getFormatter(
- # 'dateTime', 'medium')
- status = _("Updated on ${date_time}")
- # status.mapping = {'date_time': formatter.format(
- # datetime.utcnow())}
- status.mapping = {'date_time': str(datetime.utcnow())}
+ #formatter = self.request.locale.dates.getFormatter(
+ # 'dateTime', 'medium')
+ #status = _("Updated on ${date_time}",
+ # mapping={'date_time':
+ # formatter.format(datetime.utcnow())})
+ status = _("Updated on ${date_time}",
+ mapping={'date_time': str(datetime.utcnow())})
self.update_status = status
return status
@@ -249,9 +250,3 @@
def nextURL(self):
return self.context.nextURL()
-
-
-# BBB: Will be removed in future versions
-from Products.Five import browser
-browser.AddView = AddView
-browser.EditView = EditView
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/metaconfigure.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/metaconfigure.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/metaconfigure.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -13,28 +13,29 @@
##############################################################################
"""Edit form directives
-$Id: metaconfigure.py 12884 2005-05-30 13:10:41Z philikon $
+$Id: metaconfigure.py 19283 2005-10-31 17:43:51Z philikon $
"""
import ExtensionClass
+from Globals import InitializeClass as initializeClass
-from zope.component import getGlobalService
-from zope.component.servicenames import Presentation
+from zope.interface import Interface
from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.app.publisher.browser.globalbrowsermenuservice import \
- menuItemDirective
+
+from zope.app import zapi
+from zope.app.publisher.browser.menumeta import menuItemDirective
from zope.app.form.browser.metaconfigure import BaseFormDirective
from zope.app.container.interfaces import IAdding
+from zope.app.i18n import ZopeMessageFactory as _
from Products.Five.form import EditView, AddView
from Products.Five.metaclass import makeClass
-from Products.Five.security import protectClass, initializeClass
+from Products.Five.security import protectClass
from Products.Five.browser.pagetemplatefile import ZopeTwoPageTemplateFile
from Products.Five.browser.metaconfigure import makeClassForTemplate
def EditViewFactory(name, schema, label, permission, layer,
template, default_template, bases, for_, fields,
fulledit_path=None, fulledit_label=None, menu=u''):
- s = getGlobalService(Presentation)
class_ = makeClassForTemplate(template, globals(), used_for=schema,
bases=bases)
class_.schema = schema
@@ -49,8 +50,15 @@
class_.generated_form = ZopeTwoPageTemplateFile(default_template)
+ if layer is None:
+ layer = IDefaultBrowserLayer
- s.provideView(for_, name, IBrowserRequest, class_, layer)
+ s = zapi.getGlobalSiteManager()
+ s.provideAdapter((for_, layer), Interface, name, class_)
+
+ # Reminder: the permission we got has already been processed by
+ # BaseFormDirective, that means that zope.Public has been
+ # translated to the CheckerPublic object
protectClass(class_, permission)
initializeClass(class_)
@@ -58,20 +66,22 @@
def _processWidgets(self):
if self._widgets:
- customWidgetsObject = makeClass('CustomWidgetsMixin', (ExtensionClass.Base,), self._widgets)
+ customWidgetsObject = makeClass(
+ 'CustomWidgetsMixin', (ExtensionClass.Base,), self._widgets)
self.bases = self.bases + (customWidgetsObject,)
class EditFormDirective(FiveFormDirective):
view = EditView
default_template = 'edit.pt'
- title = 'Edit'
+ title = _('Edit')
def _handle_menu(self):
if self.menu:
menuItemDirective(
self._context, self.menu, self.for_ or self.schema,
- '@@' + self.name, self.title, permission=self.permission)
+ '@@' + self.name, self.title, permission=self.permission,
+ layer=self.layer)
def __call__(self):
self._processWidgets()
@@ -89,8 +99,6 @@
fields, content_factory, arguments,
keyword_arguments, set_before_add, set_after_add,
menu=u''):
-
- s = getGlobalService(Presentation)
class_ = makeClassForTemplate(template, globals(), used_for=schema,
bases=bases)
@@ -105,7 +113,15 @@
class_.generated_form = ZopeTwoPageTemplateFile(default_template)
- s.provideView(for_, name, IBrowserRequest, class_, layer)
+ if layer is None:
+ layer = IDefaultBrowserLayer
+
+ s = zapi.getGlobalSiteManager()
+ s.provideAdapter((for_, layer), Interface, name, class_)
+
+ # Reminder: the permission we got has already been processed by
+ # BaseFormDirective, that means that zope.Public has been
+ # translated to the CheckerPublic object
protectClass(class_, permission)
initializeClass(class_)
@@ -132,7 +148,7 @@
# for=self.schema.
menuItemDirective(
self._context, self.menu, self.for_, '@@' + self.name,
- self.title, permission=self.permission,
+ self.title, permission=self.permission, layer=self.layer,
description=self.description)
def _handle_arguments(self, leftover=None):
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/objectwidget.pt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/objectwidget.pt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/objectwidget.pt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,15 @@
+<fieldset>
+ <legend tal:content="context/legendTitle"
+ i18n:translate="">The Legend</legend>
+ <div class="row" tal:repeat="widget context/subwidgets">
+ <tal:comment condition="nothing">
+ This is why we have to duplicate this template: we want to look
+ up the @@form_macros browser page from something that's
+ definitely five:traversable (it doesn't really matter where we
+ look it up, just *that* we look it up); we know the object we're
+ editing is five:traversable, so we just use that. Yes, three
+ times context. Weird, eh?
+ </tal:comment>
+ <metal:block use-macro="context/context/context/@@form_macros/widget_row" />
+ </div>
+</fieldset>
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/objectwidget.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/objectwidget.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/objectwidget.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/objectwidget.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,66 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
+"""Five-compatible version of ObjectWidget
+
+This is needed because ObjectWidget uses ViewPageTemplateFile whose
+macro definition is unfortunately incompatible with
+ZopeTwoPageTemplateFile. So this subclass uses
+ZopeTwoPageTemplateFile for the template that renders the widget's
+sub-editform. Acquisition has to be mixed in to provide the
+ZopeTwoPageTemplateFile with the proper acquisition context.
+
+$Id$
+"""
+import os.path
+import Acquisition
+import zope.app.form.browser.objectwidget
+from AccessControl import ClassSecurityInfo
+from Globals import InitializeClass as initializeClass
+from Products.Five.browser.pagetemplatefile import ZopeTwoPageTemplateFile
+
+class ObjectWidgetView(Acquisition.Explicit,
+ zope.app.form.browser.objectwidget.ObjectWidgetView):
+ security = ClassSecurityInfo()
+ security.declareObjectPublic()
+
+ template = ZopeTwoPageTemplateFile('objectwidget.pt')
+
+initializeClass(ObjectWidgetView)
+
+class ObjectWidgetClass(Acquisition.Explicit,
+ zope.app.form.browser.objectwidget.ObjectWidget):
+
+ def __init__(self, context, request, factory, **kw):
+ super(ObjectWidgetClass, self).__init__(context, request, factory, **kw)
+ self.view = ObjectWidgetView(self, request)
+
+ def setRenderedValue(self, value):
+ """Slightly more robust re-implementation this method."""
+ # re-call setupwidgets with the content
+ self._setUpEditWidgets()
+ for name in self.names:
+ val = getattr(value, name, None)
+ if val is None:
+ # this is where we are more robust than Zope 3.2's
+ # object widget: we supply subwidgets with the default
+ # from the schema, not None (Zope 3.2's list widget
+ # breaks when the rendered value is None)
+ val = self.context.schema[name].default
+ self.getSubWidget(name).setRenderedValue(val)
+
+def ObjectWidget(context, request, factory, **kw):
+ """Return an ObjectWidget suitable in the Five environment, with
+ right acquisition context"""
+ return ObjectWidgetClass(context, request, factory, **kw
+ ).__of__(context.context)
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/objectwidget.py
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/tests/configure.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/tests/configure.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/tests/configure.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -34,7 +34,7 @@
type="zope.publisher.interfaces.browser.IBrowserRequest"
for="zope.schema.interfaces.IObject"
provides="zope.app.form.interfaces.IInputWidget"
- factory="zope.app.form.browser.objectwidget.ObjectWidget"
+ factory="Products.Five.form.objectwidget.ObjectWidget"
permission="zope.Public"
/>
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/tests/forms.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/tests/forms.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/tests/forms.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -17,7 +17,7 @@
Finally, we need to setup a traversable folder. Otherwise, Five won't
get to to do its view lookup:
- >>> from Products.Five.testing import manage_addFiveTraversableFolder
+ >>> from Products.Five.tests.testing import manage_addFiveTraversableFolder
>>> manage_addFiveTraversableFolder(self.folder, 'ftf')
@@ -47,9 +47,10 @@
>>> print http(r"""
... GET /test_folder_1_/ftf/+/protectedaddform.html HTTP/1.1
- ... """, handle_errors=True)
- HTTP/1.1 401 Unauthorized
+ ... """, handle_errors=False)
+ Traceback (most recent call last):
...
+ Unauthorized: ...
Now let's add a piece of our sample content object to test more things
on it:
@@ -372,7 +373,11 @@
... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="field.somelist.add"
...
- ... Add
+ ... Add Some item
+ ... -----------------------------968064918930967154199105236
+ ... Content-Disposition: form-data; name="field.somelist.count"
+ ...
+ ... 0
... -----------------------------968064918930967154199105236--
... """ % (wo_hen_hao, ni_hao), handle_errors=False)
HTTP/1.1 200 OK
@@ -408,6 +413,10 @@
...
... %s
... -----------------------------968064918930967154199105236
+ ... Content-Disposition: form-data; name="field.somelist.count"
+ ...
+ ... 1
+ ... -----------------------------968064918930967154199105236
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Change
@@ -572,5 +581,5 @@
Finally, we need to clean up:
- >>> from zope.app.tests.placelesssetup import tearDown
+ >>> from zope.app.testing.placelesssetup import tearDown
>>> tearDown()
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/tests/schemacontent.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/tests/schemacontent.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/tests/schemacontent.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -18,13 +18,13 @@
from OFS.SimpleItem import SimpleItem
from Globals import InitializeClass
-from zope.i18nmessageid import MessageIDFactory
+from zope.i18nmessageid import MessageFactory
from zope.interface import implements, Interface
from zope.schema import TextLine, Text, Object, Int, List
from zope.app.form import CustomWidgetFactory
-from zope.app.form.browser import ObjectWidget
+from Products.Five.form.objectwidget import ObjectWidget
-_ = MessageIDFactory('formtest')
+_ = MessageFactory('formtest')
class IFieldContent(Interface):
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/tests/test_forms.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/tests/test_forms.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/form/tests/test_forms.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -46,25 +46,26 @@
>>> from zope.app.form.browser.textwidgets import TextWidget
>>> from zope.app.form.browser.itemswidgets import DropdownWidget
- >>> view1 = zapi.getViewProviding(contactname, IInputWidget, request)
+ >>> view1 = zapi.getMultiAdapter((contactname, request), IInputWidget)
>>> view1.__class__ == TextWidget
True
- >>> view2 = zapi.getViewProviding(salutation, IInputWidget, request)
+ >>> view2 = zapi.getMultiAdapter((salutation, request), IInputWidget)
>>> view2.__class__ == DropdownWidget
True
Clean up:
- >>> from zope.app.tests.placelesssetup import tearDown
+ >>> from zope.app.testing.placelesssetup import tearDown
>>> tearDown()
"""
def test_suite():
import unittest
- from Testing.ZopeTestCase import ZopeDocTestSuite, FunctionalDocFileSuite
+ from zope.testing.doctest import DocTestSuite
+ from Testing.ZopeTestCase import FunctionalDocFileSuite
return unittest.TestSuite((
- ZopeDocTestSuite(),
+ DocTestSuite(),
FunctionalDocFileSuite('forms.txt',
package="Products.Five.form.tests",),
))
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/i18n.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/i18n.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/i18n.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -13,15 +13,21 @@
##############################################################################
"""Mimick Zope3 i18n machinery for Zope 2
-$Id: i18n.py 14400 2005-07-07 17:55:08Z philikon $
+$Id: i18n.py 19435 2005-11-02 16:34:58Z philikon $
"""
+from Acquisition import aq_acquire
from zope.interface import implements
from zope.i18n import interpolate
from zope.i18n.interfaces import ITranslationDomain, IUserPreferredLanguages
-from zope.i18nmessageid import MessageID
from zope.app import zapi
from zope.publisher.browser import BrowserLanguages
+# BBB 2005/10/10 -- MessageIDs are to be removed for Zope 3.3
+import zope.deprecation
+zope.deprecation.__show__.off()
+from zope.i18nmessageid import MessageID, Message
+zope.deprecation.__show__.on()
+
class FiveTranslationService:
"""Translation service that delegates to ``zope.i18n`` machinery.
"""
@@ -29,7 +35,7 @@
# regarding fallback and Zope 2 compatability
def translate(self, domain, msgid, mapping=None,
context=None, target_language=None, default=None):
- if isinstance(msgid, MessageID):
+ if isinstance(msgid, (Message, MessageID)):
domain = msgid.domain
default = msgid.default
mapping = msgid.mapping
@@ -46,7 +52,7 @@
# in Zope3, context is adapted to IUserPreferredLanguages,
# which means context should be the request in this case.
if context is not None:
- context = context.REQUEST
+ context = aq_acquire(context, 'REQUEST', None)
return util.translate(msgid, mapping=mapping, context=context,
target_language=target_language, default=default)
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/interfaces.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/interfaces.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/interfaces.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -13,7 +13,7 @@
##############################################################################
"""Five interfaces
-$Id: interfaces.py 14613 2005-07-13 10:39:05Z philikon $
+$Id: interfaces.py 19283 2005-10-31 17:43:51Z philikon $
"""
from zope.interface import Interface
from zope.interface.interfaces import IInterface
@@ -33,23 +33,3 @@
Menu item types are interfaces that define classes of
menu items.
"""
-
-
-#
-# BBB: Zope core interfaces
-#
-# The interfaces here are only provided for backwards compatibility and will
-# be removed in Five 1.2. Please import interfaces from the corresponding Zope
-# package instead.
-#
-
-from persistent.interfaces import IPersistent
-from AccessControl.interfaces import *
-from Acquisition.interfaces import *
-from App.interfaces import *
-from OFS.interfaces import *
-from webdav.interfaces import *
-
-# BBB: for old names used in Five 1.0
-IAcquisition = IAcquirer
-IPermissionMapping = IPermissionMappingSupport
Deleted: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/interfaces.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/interfaces.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/interfaces.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -1,140 +0,0 @@
-<configure xmlns="http://namespaces.zope.org/five">
-
- <!-- IPersistent, IPersistentExtra -->
-
- <!-- Acquisition -->
-
- <implements
- class="Acquisition.ImplicitAcquisitionWrapper"
- interface="Acquisition.interfaces.IAcquisitionWrapper"
- />
-
- <implements
- class="Acquisition.ExplicitAcquisitionWrapper"
- interface="Acquisition.interfaces.IAcquisitionWrapper"
- />
-
- <implements
- class="Acquisition.Implicit"
- interface="Acquisition.interfaces.IAcquirer"
- />
-
- <implements
- class="Acquisition.Explicit"
- interface="Acquisition.interfaces.IAcquirer"
- />
-
- <!-- DAV -->
-
- <implements
- class="webdav.Lockable.LockableItem"
- interface="webdav.interfaces.IWriteLock"
- />
-
- <implements
- class="webdav.Resource.Resource"
- interface="webdav.interfaces.IDAVResource"
- />
-
- <implements
- class="webdav.Collection.Collection"
- interface="webdav.interfaces.IDAVCollection"
- />
-
- <!-- OFS -->
-
- <implements
- class="OFS.CopySupport.CopySource"
- interface="OFS.interfaces.ICopySource"
- />
-
- <implements
- class="OFS.CopySupport.CopyContainer"
- interface="OFS.interfaces.ICopyContainer"
- />
-
- <implements
- class="OFS.Traversable.Traversable"
- interface="OFS.interfaces.ITraversable"
- />
-
- <implements
- class="OFS.SimpleItem.Item"
- interface="OFS.interfaces.IItem"
- />
-
- <implements
- class="OFS.SimpleItem.Item_w__name__"
- interface="OFS.interfaces.IItemWithName"
- />
-
- <implements
- class="OFS.SimpleItem.SimpleItem"
- interface="OFS.interfaces.ISimpleItem"
- />
-
- <implements
- class="OFS.ObjectManager.ObjectManager"
- interface="OFS.interfaces.IObjectManager"
- />
-
- <implements
- class="OFS.PropertyManager.PropertyManager"
- interface="OFS.interfaces.IPropertyManager"
- />
-
- <implements
- class="OFS.FindSupport.FindSupport"
- interface="OFS.interfaces.IFindSupport"
- />
-
- <implements
- class="OFS.Folder.Folder"
- interface="OFS.interfaces.IFolder"
- />
-
- <implements
- class="OFS.OrderSupport.OrderSupport"
- interface="OFS.interfaces.IOrderedContainer"
- />
-
- <implements
- class="OFS.OrderedFolder.OrderedFolder"
- interface="OFS.interfaces.IOrderedFolder"
- />
-
- <implements
- class="OFS.Application.Application"
- interface="OFS.interfaces.IApplication"
- />
-
- <!-- App -->
-
- <implements
- class="App.Undo.UndoSupport"
- interface="App.interfaces.IUndoSupport"
- />
-
- <implements
- class="App.Management.Navigation"
- interface="App.interfaces.INavigation"
- />
-
- <!-- AccessControl -->
-
- <implements
- class="AccessControl.Owned.Owned"
- interface="AccessControl.interfaces.IOwned"
- />
-
- <implements
- class="AccessControl.PermissionMapping.RoleManager"
- interface="AccessControl.interfaces.IPermissionMappingSupport"
- />
-
- <implements
- class="AccessControl.Role.RoleManager"
- interface="AccessControl.interfaces.IRoleManager"
- />
-
-</configure>
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/meta.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/meta.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/meta.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -2,13 +2,10 @@
xmlns="http://namespaces.zope.org/zope"
xmlns:meta="http://namespaces.zope.org/meta">
+ <include package=".site" file="meta.zcml" />
<include package=".browser" file="meta.zcml" />
<include package=".form" file="meta.zcml" />
- <!-- load the zope:modulealias and zope:hook directives -->
- <include package="zope.modulealias" file="meta.zcml" />
- <include package="zope.configuration" file="meta.zcml" />
-
<meta:directives namespace="http://namespaces.zope.org/zope">
<meta:directive
@@ -53,18 +50,6 @@
handler="zope.app.component.metaconfigure.factory"
/>
- <meta:directive
- name="serviceType"
- schema="zope.app.component.metadirectives.IServiceTypeDirective"
- handler="zope.app.component.metaconfigure.serviceType"
- />
-
- <meta:directive
- name="service"
- schema="zope.app.component.metadirectives.IServiceDirective"
- handler="zope.app.component.metaconfigure.service"
- />
-
<meta:complexDirective
name="content"
schema="zope.app.component.metadirectives.IClassDirective"
@@ -131,14 +116,20 @@
/>
<meta:directive
- name="sendEvents"
- schema=".fivedirectives.ISendEventsDirective"
- handler=".eventconfigure.sendEvents"
+ name="containerEvents"
+ schema=".fivedirectives.IContainerEventsDirective"
+ handler=".eventconfigure.containerEvents"
/>
<meta:directive
+ name="deprecatedManageAddDelete"
+ schema=".fivedirectives.IDeprecatedManageAddDeleteDirective"
+ handler=".eventconfigure.deprecatedManageAddDelete"
+ />
+
+ <meta:directive
name="sizable"
- schema=".fivedirectives.ISendEventsDirective"
+ schema=".fivedirectives.ISizableDirective"
handler=".sizeconfigure.sizable"
/>
@@ -148,20 +139,18 @@
handler=".fiveconfigure.pagesFromDirectory"
/>
- <!-- viewable is deprecated, use traversable instead -->
-
<meta:directive
- name="viewable"
- schema=".fivedirectives.ITraversableDirective"
- handler=".fiveconfigure.viewable"
- />
-
- <meta:directive
name="bridge"
schema=".fivedirectives.IBridgeDirective"
handler=".fiveconfigure.bridge"
/>
+ <meta:directive
+ name="registerClass"
+ schema=".fivedirectives.IRegisterClassDirective"
+ handler=".fiveconfigure.registerClass"
+ />
+
</meta:directives>
<meta:directive
@@ -171,6 +160,9 @@
handler="zope.app.security.metaconfigure.redefinePermission"
/>
+ <!-- load the zope:modulealias directive -->
+ <include package="zope.modulealias" file="meta.zcml" />
+
<!-- load the i18n:registerTranslations directive -->
<include package="zope.app.i18n" file="meta.zcml" />
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/metaconfigure.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/metaconfigure.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/metaconfigure.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -13,73 +13,25 @@
##############################################################################
"""Generic Components ZCML Handlers
-$Id: metaconfigure.py 12884 2005-05-30 13:10:41Z philikon $
+$Id: metaconfigure.py 19283 2005-10-31 17:43:51Z philikon $
"""
-from types import ModuleType
+from Products.Five.security import CheckerPublic, protectName
+from Globals import InitializeClass as initializeClass
-from zope.interface import classImplements
-from zope.configuration.exceptions import ConfigurationError
+from zope.app.component.contentdirective import ContentDirective as \
+ zope_app_ContentDirective
-from security import CheckerPublic
-from security import protectName, initializeClass
-
-class ContentDirective:
-
- def __init__(self, _context, class_):
- self.__class = class_
- if isinstance(self.__class, ModuleType):
- raise ConfigurationError('Content class attribute must be a class')
- self.__context = _context
-
- def implements(self, _context, interface):
- for interface in interface:
- _context.action(
- discriminator = (
- 'five::directive:content', self.__class, object()),
- callable = classImplements,
- args = (self.__class, interface),
- )
- interface(_context, interface)
-
- def require(self, _context, permission=None,
- attributes=None, interface=None):
- """Require a the permission to access a specific aspect"""
-
- if not (interface or attributes):
- raise ConfigurationError("Nothing required")
-
- if interface:
- for i in interface:
- if i:
- self.__protectByInterface(i, permission)
- if attributes:
- self.__protectNames(attributes, permission)
-
- def allow(self, _context, attributes=None, interface=None):
- """Like require, but with permission_id zope.Public"""
- return self.require(_context, CheckerPublic, 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)
- interface(self.__context, interface)
-
+class ContentDirective(zope_app_ContentDirective):
+
def __protectName(self, name, permission_id):
- "Set a permission on a particular name."
self.__context.action(
discriminator = ('five:protectName', self.__class, name),
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 __call__(self):
- "Handle empty/simple declaration."
+ """Handle empty/simple declaration."""
return self.__context.action(
discriminator = ('five:initialize:class', self.__class),
callable = initializeClass,
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/permissions.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/permissions.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/permissions.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -1,6 +1,11 @@
<configure xmlns="http://namespaces.zope.org/zope"
i18n_domain="Five">
+ <permission
+ id="five.ManageSite"
+ title="Manage Five local sites"
+ />
+
<!-- Give common Zope2 and CMF permissions a permission ID
The title of the permission is what Zope 2 knows it under -->
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/security.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/security.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/security.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -24,7 +24,7 @@
from zope.app import zapi
from AccessControl import ClassSecurityInfo, getSecurityManager
-from Globals import InitializeClass
+from Globals import InitializeClass as initializeClass
from types import StringTypes
CheckerPublicId = 'zope.Public'
@@ -99,9 +99,6 @@
if getattr(thread_local, 'interaction', None) is None:
thread_local.interaction = FiveSecurityPolicy()
-def initializeClass(klass):
- InitializeClass(klass)
-
def _getSecurity(klass):
# a Zope 2 class can contain some attribute that is an instance
# of ClassSecurityInfo. Zope 2 scans through things looking for
@@ -121,15 +118,12 @@
"""Protect the attribute 'name' on 'klass' using the given
permission"""
security = _getSecurity(klass)
- # XXX: Sometimes, the object CheckerPublic is used instead of the
- # string zope.Public. I haven't ben able to figure out why, or if
- # it is correct, or a bug. So this is a workaround.
- if permission_id is CheckerPublic:
- security.declarePublic(name)
- return
# Zope 2 uses string, not unicode yet
name = str(name)
- if permission_id == CheckerPublicId:
+ if permission_id == CheckerPublicId or permission_id is CheckerPublic:
+ # Sometimes, we already get a processed permission id, which
+ # can mean that 'zope.Public' has been interchanged for the
+ # CheckerPublic object
security.declarePublic(name)
elif permission_id == CheckerPrivateId:
security.declarePrivate(name)
@@ -142,7 +136,10 @@
def protectClass(klass, permission_id):
"""Protect the whole class with the given permission"""
security = _getSecurity(klass)
- if permission_id == CheckerPublicId:
+ if permission_id == CheckerPublicId or permission_id is CheckerPublic:
+ # Sometimes, we already get a processed permission id, which
+ # can mean that 'zope.Public' has been interchanged for the
+ # CheckerPublic object
security.declareObjectPublic()
elif permission_id == CheckerPrivateId:
security.declareObjectPrivate()
Deleted: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/services.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/services.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/services.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -1,27 +0,0 @@
-<configure xmlns="http://namespaces.zope.org/zope">
-
- <serviceType
- id="Utilities"
- interface="zope.component.interfaces.IUtilityService" />
-
- <service
- serviceType="Utilities"
- factory="zope.component.utility.GlobalUtilityService" />
-
- <serviceType
- id="Adapters"
- interface="zope.component.interfaces.IAdapterService" />
-
- <service
- serviceType="Adapters"
- factory="zope.component.adapter.GlobalAdapterService" />
-
- <serviceType
- id="Presentation"
- interface="zope.component.interfaces.IPresentationService" />
-
- <service
- serviceType="Presentation"
- factory="zope.component.presentation.GlobalPresentationService" />
-
-</configure>
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/__init__.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/__init__.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/__init__.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1 @@
+# make this directory a package
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/browser.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/browser.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/browser.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,61 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
+"""Local sites browser views
+
+$Id$
+"""
+from zope.app.component.interfaces import ISite
+from zope.app.component.hooks import clearSite
+
+from Products.Five.browser import BrowserView
+from Products.Five.site.localsite import enableLocalSiteHook, \
+ disableLocalSiteHook
+
+class LocalSiteView(BrowserView):
+ """View for convering a possible site to a site
+ """
+
+ def update(self):
+ form = self.request.form
+ if form.has_key('UPDATE_MAKESITE'):
+ self.makeSite()
+ elif form.has_key('UPDATE_UNMAKESITE'):
+ self.unmakeSite()
+
+ def isSite(self):
+ return ISite.providedBy(self.context)
+
+ def makeSite(self):
+ """Convert a possible site to a site"""
+ if self.isSite():
+ raise ValueError('This is already a site')
+
+ enableLocalSiteHook(self.context)
+ return "This object is now a site"
+
+ def unmakeSite(self):
+ """Convert a site to a possible site"""
+ if not self.isSite():
+ raise ValueError('This is not a site')
+
+ disableLocalSiteHook(self.context)
+
+ # disableLocalSiteHook circumcised our context so that it's
+ # not an ISite anymore. That can mean that certain things for
+ # it can't be found anymore. So, for the rest of this request
+ # (which will be over in about 20 CPU cycles), already clear
+ # the local site from the thread local.
+ clearSite()
+
+ return "This object is no longer a site"
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/browser.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/configure.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/configure.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/configure.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,35 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+ xmlns:browser="http://namespaces.zope.org/browser">
+
+ <adapter
+ for="*"
+ provides="zope.component.interfaces.ISiteManager"
+ factory=".localsite.siteManagerAdapter"
+ />
+
+ <adapter
+ for="zope.app.site.interfaces.ISite"
+ provides=".interfaces.IFiveUtilityRegistry"
+ factory=".utility.SimpleLocalUtilityRegistry"
+ />
+
+ <subscriber
+ for="zope.app.component.interfaces.ISite
+ zope.app.publication.interfaces.IBeforeTraverseEvent"
+ handler="zope.app.component.site.threadSiteSubscriber"
+ />
+
+ <subscriber
+ for="zope.app.publication.interfaces.IEndRequestEvent"
+ handler="zope.app.component.site.clearThreadSiteSubscriber"
+ />
+
+ <browser:page
+ for="zope.app.component.interfaces.IPossibleSite"
+ name="manage_site.html"
+ permission="five.ManageSite"
+ class=".browser.LocalSiteView"
+ template="managesite.pt"
+ />
+
+</configure>
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/configure.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/interfaces.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/interfaces.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/interfaces.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,95 @@
+##############################################################################
+#
+# Copyright (c) 2004, 2005 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.
+#
+##############################################################################
+"""Five interfaces
+
+$Id: interfaces.py 18584 2005-10-14 17:13:27Z regebro $
+"""
+from zope.interface import Interface, Attribute
+from zope.component.interfaces import ISiteManager
+
+class IRegisterUtilitySimply(Interface):
+ """Register utilities simply
+
+ Allow local registrations of utilities, in a much simpler
+ manner than Zope 3 does it currently.
+
+ Note: The name of this interface is expressed as a verb
+ (describing the action it expresses, namely registering
+ utilities). The reason for that is that the names *utility
+ registry* (successor of the Zope 3 utility service) and *utility
+ registration* (object in a registration stack, part of the
+ complicated registration framework in Zope 3) have different
+ connotations in Zope 3 than we want to express here.
+ """
+
+ def registerUtility(self, interface, utility, name=''):
+ """Registers a utility in the local context"""
+ # TODO Define an exception than is to be thrown when a local
+ # utility of that interface and name is already registered.
+
+ next = Attribute("The next local registry in the tree. This attribute "
+ "represents the parent of this registry node. If the "
+ "value is ``None``, then this registry represents the "
+ "root of the tree")
+
+class IFiveUtilityRegistry(IRegisterUtilitySimply):
+ """Look up and register utilities"""
+
+ def getUtility(interface, name='', context=None):
+ """Get the utility that provides interface
+
+ Returns the nearest utility to the context that implements the
+ specified interface. If one is not found, raises
+ ComponentLookupError.
+ """
+
+ def queryUtility(interface, name='', default=None, context=None):
+ """Look for the utility that provides interface
+
+ Returns the nearest utility to the context that implements
+ the specified interface. If one is not found, returns default.
+ """
+
+ def getUtilitiesFor(interface, context=None):
+ """Return the utilities that provide an interface
+
+ An iterable of utility name-value pairs is returned.
+ """
+
+ def getAllUtilitiesRegisteredFor(interface, context=None):
+ """Return all registered utilities for an interface
+
+ This includes overridden utilities.
+
+ An iterable of utility instances is returned. No names are
+ returned.
+ """
+
+class IFiveSiteManager(ISiteManager, IRegisterUtilitySimply):
+ """Five site manager
+
+ For the sake of forward-portability, registering utilities can be
+ done directly on the site manager to cut out the middle man called
+ utility service (this corresponds to Zope 3.1's understanding of
+ site managers). An implementation of this interface will probably
+ delegate the work to an IFiveUtilityService component, though."""
+
+
+# BBB 2005/11/01 -- gone in Five 1.5.
+IFiveUtilityService = IFiveUtilityRegistry
+import zope.deprecation
+zope.deprecation.deprecated(
+ 'IFiveUtilityService', "'IFiveUtilityService' has been renamed to "
+ "'IFiveUtilityRegistry' and will disappear in Five 1.5."
+ )
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/interfaces.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/localsite.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/localsite.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/localsite.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,151 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
+"""Local sites
+
+$Id$
+"""
+from zope.event import notify
+from zope.interface import directlyProvides, directlyProvidedBy
+from zope.interface import implements
+from zope.component import getGlobalSiteManager
+from zope.component.exceptions import ComponentLookupError
+
+from zope.app.component.interfaces import ISite, IPossibleSite
+from zope.app.publication.zopepublication import BeforeTraverseEvent
+
+from ExtensionClass import Base
+from Acquisition import aq_base, aq_inner, aq_parent
+from Products.SiteAccess.AccessRule import AccessRule
+from ZPublisher.BeforeTraverse import registerBeforeTraverse
+from ZPublisher.BeforeTraverse import unregisterBeforeTraverse
+
+from Products.Five.site.interfaces import IFiveSiteManager, IFiveUtilityRegistry
+
+# Hook up custom component architecture calls
+import zope.app.component.hooks
+zope.app.component.hooks.setHooks()
+
+def siteManagerAdapter(ob):
+ """An adapter * -> ISiteManager.
+
+ This is registered in place of the one in Zope 3 so that we lookup
+ using acquisition instead of ILocation.
+ """
+ current = ob
+ while True:
+ if ISite.providedBy(current):
+ return current.getSiteManager()
+ current = getattr(current, '__parent__', aq_parent(aq_inner(current)))
+ if current is None:
+ # It does not support acquisition or has no parent, so we
+ # return the global site
+ return getGlobalSiteManager()
+
+HOOK_NAME = '__local_site_hook__'
+
+class LocalSiteHook(Base):
+ def __call__(self, container, request):
+ notify(BeforeTraverseEvent(container, request))
+
+
+def enableLocalSiteHook(obj):
+ """Install __before_traverse__ hook for Local Site
+ """
+ # We want the original object, not stuff in between, and no acquisition
+ obj = aq_base(obj)
+ if not IPossibleSite.providedBy(obj):
+ raise TypeError, 'Must provide IPossibleSite'
+ hook = AccessRule(HOOK_NAME)
+ registerBeforeTraverse(obj, hook, HOOK_NAME, 1)
+
+ if not hasattr(obj, HOOK_NAME):
+ setattr(obj, HOOK_NAME, LocalSiteHook())
+
+ directlyProvides(obj, ISite, directlyProvidedBy(obj))
+
+def disableLocalSiteHook(obj):
+ """Remove __before_traverse__ hook for Local Site
+ """
+ # We want the original object, not stuff in between, and no acquisition
+ obj = aq_base(obj)
+ if not ISite.providedBy(obj):
+ raise TypeError, 'Must provide ISite'
+ unregisterBeforeTraverse(obj, HOOK_NAME)
+ if hasattr(obj, HOOK_NAME):
+ delattr(obj, HOOK_NAME)
+
+ directlyProvides(obj, directlyProvidedBy(obj) - ISite)
+
+class FiveSiteManager(object):
+ implements(IFiveSiteManager)
+
+ def __init__(self, context):
+ # make {get|query}NextSiteManager() work without having to
+ # resort to Zope 2 acquisition
+ self.context = self.__parent__ = context
+
+ @property
+ def next(self):
+ obj = self.context
+ while obj is not None:
+ obj = aq_parent(aq_inner(obj))
+ if ISite.providedBy(obj):
+ return obj.getSiteManager()
+ # In Zope 3.1+, returning None here is understood by
+ # getNextSiteManager as that our next site manager is the
+ # global one. If we returned the global one, it would be
+ # understood as a lookup error. Yeah, it's weird, tell me
+ # about it.
+ return None
+
+ @property
+ def adapters(self):
+ return getGlobalSiteManager().adapters #XXX wrong
+
+ @property
+ def utilities(self):
+ return IFiveUtilityRegistry(self.context)
+
+ def queryAdapter(self, object, interface, name, default=None):
+ return self.adapters.queryAdapter(object, interface, name, default)
+
+ def queryMultiAdapter(self, objects, interface, name, default=None):
+ return self.adapters.queryMultiAdapter(objects, interface, name, default)
+
+ def getAdapters(self, objects, provided):
+ return self.adapters.getAdapters(objects, provided)
+
+ def subscribers(self, required, provided):
+ return self.adapters.subscribers(required, provided)
+
+ def queryUtility(self, interface, name='', default=None):
+ return self.utilities.queryUtility(interface, name, default)
+
+ def getUtilitiesFor(self, interface):
+ return self.utilities.getUtilitiesFor(interface)
+
+ def getAllUtilitiesRegisteredFor(self, interface):
+ return self.utilities.getAllUtilitiesRegisteredFor(interface)
+
+ def registerUtility(self, interface, utility, name=''):
+ return self.utilities.registerUtility(interface, utility, name)
+
+class FiveSite:
+ implements(IPossibleSite)
+
+ def getSiteManager(self):
+ return FiveSiteManager(self)
+
+ def setSiteManager(self, sm):
+ raise NotImplementedError('This class has a fixed site manager')
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/localsite.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/managesite.pt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/managesite.pt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/managesite.pt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,25 @@
+<tal:tag condition="view/update"/>
+<html metal:use-macro="context/@@standard_macros/view"
+ i18n:domain="zope">
+ <body>
+ <div metal:fill-slot="body">
+
+ <form action="." tal:attributes="action request/URL" method="POST"
+ enctype="multipart/form-data">
+ <div class="row">
+ <div class="controls">
+ <input type="submit" value="Make site" name="UPDATE_MAKESITE"
+ i18n:attributes="value"
+ tal:attributes="disabled view/isSite"/>
+ <input type="submit" value="Unmake site" name="UPDATE_UNMAKESITE"
+ i18n:attributes="value"
+ tal:attributes="disabled not:view/isSite"/>
+
+ </div>
+ </div>
+ </form>
+
+ </div>
+ </body>
+
+</html>
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/managesite.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/meta.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/meta.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/meta.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,15 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:meta="http://namespaces.zope.org/meta">
+
+ <meta:directives namespace="http://namespaces.zope.org/five">
+
+ <meta:directive
+ name="localsite"
+ schema=".metadirectives.ILocalSiteDirective"
+ handler=".metaconfigure.installSiteHook"
+ />
+
+ </meta:directives>
+
+</configure>
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/meta.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/metaconfigure.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/metaconfigure.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/metaconfigure.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,69 @@
+##############################################################################
+#
+# Copyright (c) 2004, 2005 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.
+#
+##############################################################################
+"""Five-specific directive handlers
+
+These directives are specific to Five and have no equivalents in Zope 3.
+
+$Id: fiveconfigure.py 18581 2005-10-14 16:54:25Z regebro $
+"""
+from zope.interface import classImplements, classImplementsOnly, implementedBy
+from zope.interface.interface import InterfaceClass
+from zope.configuration.exceptions import ConfigurationError
+from zope.app.component.metaconfigure import adapter
+from zope.app.component.interfaces import IPossibleSite
+
+from Products.Five.site.localsite import FiveSite
+
+def classSiteHook(class_, site_class):
+ setattr(class_, 'getSiteManager',
+ site_class.getSiteManager.im_func)
+ setattr(class_, 'setSiteManager',
+ site_class.setSiteManager.im_func)
+
+_localsite_monkies = []
+def installSiteHook(_context, class_, site_class=None):
+ if site_class is None:
+ if not IPossibleSite.implementedBy(class_):
+ # This is not a possible site, we need to monkey-patch it so that
+ # it is.
+ site_class = FiveSite
+ else:
+ if not IPossibleSite.implementedBy(site_class):
+ raise ConfigurationError('Site class does not implement '
+ 'IPossibleClass: %s' % site_class)
+ if site_class is not None:
+ _context.action(
+ discriminator = (class_,),
+ callable = classSiteHook,
+ args=(class_, site_class)
+ )
+ _context.action(
+ discriminator = (class_, IPossibleSite),
+ callable = classImplements,
+ args=(class_, IPossibleSite)
+ )
+ _localsite_monkies.append(class_)
+
+# clean up code
+
+def uninstallSiteHooks():
+ for class_ in _localsite_monkies:
+ delattr(class_, 'getSiteManager')
+ delattr(class_, 'setSiteManager')
+ classImplementsOnly(class_, implementedBy(class_)-IPossibleSite)
+ _localsite_monkies.remove(class_)
+
+from zope.testing.cleanup import addCleanUp
+addCleanUp(uninstallSiteHooks)
+del addCleanUp
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/metaconfigure.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/metadirectives.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/metadirectives.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/metadirectives.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,36 @@
+##############################################################################
+#
+# Copyright (c) 2004, 2005 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.
+#
+##############################################################################
+"""Site support ZCML directive schemas
+
+$Id: fivedirectives.py 18581 2005-10-14 16:54:25Z regebro $
+"""
+from zope.interface import Interface
+from zope.configuration.fields import GlobalObject
+
+class ILocalSiteDirective(Interface):
+ """Make instances of class hookable for Site.
+
+ site_class is an implementation of ISite, which will have it's methods
+ monkey_patched into the the class. If not given a default implementation
+ will be used.
+ """
+ class_ = GlobalObject(
+ title=u"Class",
+ required=True
+ )
+
+ site_class = GlobalObject(
+ title=u"Site Class",
+ required=False
+ )
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/metadirectives.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/__init__.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/__init__.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/__init__.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1 @@
+# make this directory a package
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/dummy.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/dummy.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/dummy.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,42 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
+"""Dummy test fixtures
+
+$Id$
+"""
+from zope.interface import implements, Interface
+from OFS.SimpleItem import SimpleItem
+from Products.Five.tests.testing import FiveTraversableFolder
+
+class IDummySite(Interface):
+ pass
+
+class DummySite(FiveTraversableFolder):
+ """A very dummy Site
+ """
+ implements(IDummySite)
+
+def manage_addDummySite(self, id, REQUEST=None):
+ """Add the dummy site."""
+ id = self._setObject(id, DummySite(id))
+ return ''
+
+class IDummyUtility(Interface):
+ pass
+
+class ISuperDummyUtility(IDummyUtility):
+ pass
+
+class DummyUtility(SimpleItem):
+ implements(IDummyUtility)
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/dummy.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/framework.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/framework.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/framework.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,107 @@
+##############################################################################
+#
+# ZopeTestCase
+#
+# COPY THIS FILE TO YOUR 'tests' DIRECTORY.
+#
+# This version of framework.py will use the SOFTWARE_HOME
+# environment variable to locate Zope and the Testing package.
+#
+# If the tests are run in an INSTANCE_HOME installation of Zope,
+# Products.__path__ and sys.path with be adjusted to include the
+# instance's Products and lib/python directories respectively.
+#
+# If you explicitly set INSTANCE_HOME prior to running the tests,
+# auto-detection is disabled and the specified path will be used
+# instead.
+#
+# If the 'tests' directory contains a custom_zodb.py file, INSTANCE_HOME
+# will be adjusted to use it.
+#
+# If you set the ZEO_INSTANCE_HOME environment variable a ZEO setup
+# is assumed, and you can attach to a running ZEO server (via the
+# instance's custom_zodb.py).
+#
+##############################################################################
+#
+# The following code should be at the top of every test module:
+#
+# import os, sys
+# if __name__ == '__main__':
+# execfile(os.path.join(sys.path[0], 'framework.py'))
+#
+# ...and the following at the bottom:
+#
+# if __name__ == '__main__':
+# framework()
+#
+##############################################################################
+
+__version__ = '0.2.3'
+
+# Save start state
+#
+__SOFTWARE_HOME = os.environ.get('SOFTWARE_HOME', '')
+__INSTANCE_HOME = os.environ.get('INSTANCE_HOME', '')
+
+if __SOFTWARE_HOME.endswith(os.sep):
+ __SOFTWARE_HOME = os.path.dirname(__SOFTWARE_HOME)
+
+if __INSTANCE_HOME.endswith(os.sep):
+ __INSTANCE_HOME = os.path.dirname(__INSTANCE_HOME)
+
+# Find and import the Testing package
+#
+if not sys.modules.has_key('Testing'):
+ p0 = sys.path[0]
+ if p0 and __name__ == '__main__':
+ os.chdir(p0)
+ p0 = ''
+ s = __SOFTWARE_HOME
+ p = d = s and s or os.getcwd()
+ while d:
+ if os.path.isdir(os.path.join(p, 'Testing')):
+ zope_home = os.path.dirname(os.path.dirname(p))
+ sys.path[:1] = [p0, p, zope_home]
+ break
+ p, d = s and ('','') or os.path.split(p)
+ else:
+ print 'Unable to locate Testing package.',
+ print 'You might need to set SOFTWARE_HOME.'
+ sys.exit(1)
+
+import Testing, unittest
+execfile(os.path.join(os.path.dirname(Testing.__file__), 'common.py'))
+
+# Include ZopeTestCase support
+#
+if 1: # Create a new scope
+
+ p = os.path.join(os.path.dirname(Testing.__file__), 'ZopeTestCase')
+
+ if not os.path.isdir(p):
+ print 'Unable to locate ZopeTestCase package.',
+ print 'You might need to install ZopeTestCase.'
+ sys.exit(1)
+
+ ztc_common = 'ztc_common.py'
+ ztc_common_global = os.path.join(p, ztc_common)
+
+ f = 0
+ if os.path.exists(ztc_common_global):
+ execfile(ztc_common_global)
+ f = 1
+ if os.path.exists(ztc_common):
+ execfile(ztc_common)
+ f = 1
+
+ if not f:
+ print 'Unable to locate %s.' % ztc_common
+ sys.exit(1)
+
+# Debug
+#
+print 'SOFTWARE_HOME: %s' % os.environ.get('SOFTWARE_HOME', 'Not set')
+print 'INSTANCE_HOME: %s' % os.environ.get('INSTANCE_HOME', 'Not set')
+sys.stdout.flush()
+
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/framework.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/functional.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/functional.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/functional.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,147 @@
+Functional test for local sites
+===============================
+
+Set up all of Five:
+
+ >>> import Products.Five
+ >>> from Products.Five import zcml
+ >>> zcml.load_config("configure.zcml", Products.Five)
+
+First we turn our DummySite class into a site in ZCML (and register
+some views that will provide us with some test info),
+
+ >>> zcml_text = """
+ ... <configure xmlns="http://namespaces.zope.org/zope"
+ ... xmlns:meta="http://namespaces.zope.org/meta"
+ ... xmlns:five="http://namespaces.zope.org/five"
+ ... xmlns:browser="http://namespaces.zope.org/browser">
+ ...
+ ... <!-- make the zope2.Public permission work -->
+ ... <meta:redefinePermission from="zope2.Public" to="zope.Public" />
+ ...
+ ... <five:localsite class="Products.Five.site.tests.dummy.DummySite" />
+ ...
+ ... <browser:page
+ ... for="Products.Five.site.tests.dummy.IDummySite"
+ ... name="checkSiteManager.html"
+ ... class="Products.Five.site.tests.test_functional.CheckSiteManagerView"
+ ... permission="zope2.Public"
+ ... />
+ ...
+ ... <browser:page
+ ... for="Products.Five.site.tests.dummy.IDummySite"
+ ... name="lookupUtilities.html"
+ ... class="Products.Five.site.tests.test_functional.LookupUtilitiesView"
+ ... permission="zope2.Public"
+ ... />
+ ...
+ ... </configure>"""
+ >>> zcml.load_string(zcml_text)
+
+then we add an instance to our folder:
+
+ >>> from Products.Five.site.tests.dummy import manage_addDummySite
+ >>> nothing = manage_addDummySite(self.folder, 'site')
+
+Now we check what the info view tells us about local component lookup:
+
+ >>> print http(r'''
+ ... GET /test_folder_1_/site/@@checkSiteManager.html HTTP/1.1
+ ... ''')
+ HTTP/1.1 200 OK
+ ...
+ {'IFiveUtilityRegistry.providedBy(utility_service)': False,
+ 'isinstance(zapi.getSiteManager(), FiveSiteManager)': False,
+ 'zapi.getSiteManager() is zapi.getGlobalSiteManager()': True}
+
+We see that we have no local component lookup yet, because we haven't
+set the site. Therefore, enable the traversal hook by using the view
+that's provided for this task (we first need to create a manager
+account in order to be able to access it):
+
+ >>> uf = self.folder.acl_users
+ >>> uf._doAddUser('manager', 'r00t', ['Manager'], [])
+
+ >>> print http(r'''
+ ... POST /test_folder_1_/site/@@manage_site.html HTTP/1.1
+ ... Authorization: Basic manager:r00t
+ ... Content-Length: 25
+ ...
+ ... UPDATE_MAKESITE=Make site''')
+ HTTP/1.1 200 OK
+ ...
+
+Now we call the info view again and find that local component lookup
+is working:
+
+ >>> print http(r'''
+ ... GET /test_folder_1_/site/@@checkSiteManager.html HTTP/1.1
+ ... ''')
+ HTTP/1.1 200 OK
+ ...
+ {'IFiveUtilityRegistry.providedBy(utility_service)': True,
+ 'isinstance(zapi.getSiteManager(), FiveSiteManager)': True,
+ 'zapi.getSiteManager() is zapi.getGlobalSiteManager()': False}
+
+Of course, sites are only active *during* traversal; after traversal
+they're gone:
+
+ >>> from zope.app.component.hooks import getSite
+ >>> getSite() is None
+ True
+
+
+We can also register utilities now:
+
+ >>> from zope.app import zapi
+ >>> sm = self.folder.site.getSiteManager()
+
+ >>> from Products.Five.site.tests.dummy import IDummyUtility, DummyUtility
+ >>> dummy = DummyUtility()
+ >>> sm.registerUtility(IDummyUtility, dummy)
+
+and find them being looked up just fine:
+
+ >>> print http(r'''
+ ... GET /test_folder_1_/site/@@lookupUtilities.html HTTP/1.1
+ ... ''')
+ HTTP/1.1 200 OK
+ ...
+ zapi.getUtility(IDummyUtility) == dummy: True
+
+Of course, we can't look it up once the request has ended, because we
+lose the local site setup:
+
+ >>> zapi.getUtility(IDummyUtility)
+ Traceback (most recent call last):
+ ...
+ ComponentLookupError: (<InterfaceClass Products.Five.site.tests.dummy.IDummyUtility>, '')
+
+At last we can "unmake" the site using the browser view provided by
+Five:
+
+ >>> print http(r'''
+ ... POST /test_folder_1_/site/@@manage_site.html HTTP/1.1
+ ... Authorization: Basic manager:r00t
+ ... Content-Length: 29
+ ...
+ ... UPDATE_UNMAKESITE=Unmake site''')
+ HTTP/1.1 200 OK
+ ...
+
+And everything is back to normal with respect to local component
+lookup:
+
+ >>> print http(r'''
+ ... GET /test_folder_1_/site/@@checkSiteManager.html HTTP/1.1
+ ... ''')
+ HTTP/1.1 200 OK
+ ...
+ {'IFiveUtilityRegistry.providedBy(utility_service)': False,
+ 'isinstance(zapi.getSiteManager(), FiveSiteManager)': False,
+ 'zapi.getSiteManager() is zapi.getGlobalSiteManager()': True}
+
+Finally, global services and the monkeys:
+
+ >>> from zope.app.testing.placelesssetup import tearDown
+ >>> tearDown()
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/functional.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/sitemanager.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/sitemanager.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/sitemanager.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,124 @@
+Five Site Manager
+=================
+
+In this test we want to test Five's implementation of a site manager.
+First, we need to set a few things up...
+
+ >>> from zope.app.testing.placelesssetup import setUp, tearDown
+ >>> setUp()
+
+ >>> import Products.Five
+ >>> from Products.Five import zcml
+ >>> zcml.load_config("meta.zcml", Products.Five)
+ >>> zcml.load_config("permissions.zcml", Products.Five)
+ >>> zcml.load_config("configure.zcml", Products.Five.site)
+ >>> zcml_text = """\
+ ... <five:localsite
+ ... xmlns:five="http://namespaces.zope.org/five"
+ ... class="Products.Five.site.tests.dummy.DummySite" />"""
+ >>> zcml.load_string(zcml_text)
+
+...for example some sort of site object:
+
+ >>> from Products.Five.site.tests.dummy import manage_addDummySite
+ >>> nothing = manage_addDummySite(self.folder, 'dummysite')
+ >>> dummysite = self.folder.dummysite
+
+
+Local vs. global sites
+----------------------
+
+Let's make the possible site a real site:
+
+ >>> from Products.Five.site.localsite import enableLocalSiteHook
+ >>> enableLocalSiteHook(dummysite)
+
+and tell Zope 3 about it:
+
+ >>> from zope.app.component.hooks import setSite, setHooks
+ >>> setSite(dummysite)
+
+Also hook up custom component architecture calls; we need to do this
+here because zope.app.component.hooks registers a cleanup with the
+testing cleanup framework, so the hooks get torn down by
+placelesssetup each time.
+
+ >>> setHooks()
+
+That seems to have worked (we test this by using the context property
+of FiveSiteManager):
+
+ >>> from zope.app import zapi
+ >>> zapi.getSiteManager().context == dummysite
+ True
+
+Since there's no other local site in between this one and the global
+one, the next one should be the global one. FiveSiteManager indicates
+that to us by return ``None``:
+
+ >>> from zope.app import zapi
+ >>> zapi.getSiteManager().next is None
+ True
+
+To the the Zope 3 API, this means the next site manager should be the
+global one:
+
+ >>> from zope.app.component import getNextSiteManager
+ >>> getNextSiteManager(dummysite.getSiteManager()) is zapi.getGlobalSiteManager()
+ True
+
+
+ISiteManager API
+----------------
+
+Site managers are supposed to have an ``adapters`` and a ``utilities``
+attribute. Five's site manager simply passes through the global
+adapter registry:
+
+ >>> zapi.getSiteManager().adapters is zapi.getGlobalSiteManager().adapters
+ True
+
+The utility registry, however, is an ``IFiveUtilityRegistry``:
+
+ >>> from Products.Five.site.interfaces import IFiveUtilityRegistry
+ >>> IFiveUtilityRegistry.providedBy(zapi.getSiteManager().utilities)
+ True
+
+The methods on registering and looking up utilities are covered by the
+utility tests in depth. The methods on adapter look up are indirectly
+covered in the functional test; view look up, for example, is adapter
+look up.
+
+
+Nesting sites
+-------------
+
+Let's set up another site to test nested sites:
+
+ >>> nothing = manage_addDummySite(self.folder.dummysite, 'subsite')
+ >>> subsite = self.folder.dummysite.subsite
+
+Now we set the current site to the ``subsite``:
+
+ >>> enableLocalSiteHook(subsite)
+ >>> setSite(subsite)
+
+When we call getServices() now, we get the correct site manager:
+
+ >>> zapi.getSiteManager().context == subsite
+ True
+
+The "next" site is the less local one:
+
+ >>> zapi.getSiteManager().next.context == dummysite
+ True
+
+The Zope 3 API for this agrees with that:
+
+ >>> getNextSiteManager(subsite.getSiteManager()).context == dummysite
+ True
+
+
+Finally, some clean up:
+
+ >>> tearDown()
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/sitemanager.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_functional.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_functional.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_functional.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,59 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
+"""Test local sites
+
+$Id$
+"""
+import os, sys
+
+if __name__ == '__main__':
+ execfile(os.path.join(sys.path[0], 'framework.py'))
+
+import pprint
+from zope.app import zapi
+from Products.Five import BrowserView
+from Products.Five.site.interfaces import IFiveUtilityRegistry
+from Products.Five.site.localsite import FiveSiteManager
+from Products.Five.site.tests.dummy import IDummyUtility
+
+class CheckSiteManagerView(BrowserView):
+
+ def __call__(self):
+ sm = zapi.getSiteManager()
+ result = {
+ 'zapi.getSiteManager() is zapi.getGlobalSiteManager()':
+ sm is zapi.getGlobalSiteManager(),
+ 'IFiveUtilityRegistry.providedBy(utility_service)':
+ IFiveUtilityRegistry.providedBy(sm.utilities),
+ 'isinstance(zapi.getSiteManager(), FiveSiteManager)':
+ isinstance(sm, FiveSiteManager),
+ }
+ return pprint.pformat(result)
+
+class LookupUtilitiesView(BrowserView):
+
+ def __call__(self):
+ dummy = getattr(self.context.utilities, IDummyUtility.getName())
+ return "zapi.getUtility(IDummyUtility) == dummy: %s" % \
+ (zapi.getUtility(IDummyUtility) == dummy)
+
+def test_suite():
+ from Testing.ZopeTestCase import FunctionalDocFileSuite
+ suite = FunctionalDocFileSuite('functional.txt',
+ package='Products.Five.site.tests')
+ suite.level = 2
+ return suite
+
+if __name__ == '__main__':
+ framework()
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_functional.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_localsite.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_localsite.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_localsite.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,215 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
+"""Test local sites
+
+$Id$
+"""
+import os, sys
+
+if __name__ == '__main__':
+ execfile(os.path.join(sys.path[0], 'framework.py'))
+
+import unittest
+from Testing import ZopeTestCase
+
+from zope.interface import implements
+from zope.interface import directlyProvides, directlyProvidedBy
+from zope.component import getGlobalSiteManager, getSiteManager
+from zope.component.exceptions import ComponentLookupError
+from zope.component.interfaces import ISiteManager
+from zope.app.component.hooks import setSite, getSite, setHooks
+from zope.app.component.interfaces import IPossibleSite, ISite
+from zope.app.traversing.interfaces import IContainmentRoot
+from zope.app.testing.placelesssetup import PlacelessSetup
+
+from Acquisition import Implicit
+from OFS.ObjectManager import ObjectManager
+
+import Products.Five
+from Products.Five import zcml
+
+class SiteManager(Implicit):
+ implements(ISiteManager)
+
+class Folder(ObjectManager):
+ implements(IPossibleSite)
+
+ sm = None
+
+ def getId(self):
+ return self.id
+
+ def getSiteManager(self, default=None):
+ return self.sm
+
+ def setSiteManager(self, sm):
+ self.sm = sm
+ directlyProvides(self, ISite, directlyProvidedBy(self))
+
+class Package(Implicit):
+ pass
+
+class Root(Folder):
+ implements(IContainmentRoot, ISite)
+ def getSiteManager(self):
+ return getGlobalSiteManager()
+
+class SiteManagerStub(object):
+ implements(ISiteManager)
+
+class SiteManagerTest(PlacelessSetup, unittest.TestCase):
+
+ def setUp(self):
+ super(SiteManagerTest, self).setUp()
+ self.root = root = Root()
+
+ self.f1 = f1 = Folder().__of__(root)
+ self.sm1 = sm1 = SiteManager()
+ f1.setSiteManager(sm1)
+ self.p1 = p1 = Package().__of__(sm1)
+
+ self.f2 = f2 = Folder().__of__(f1)
+ self.sm2 = sm2 = SiteManager()
+ f2.setSiteManager(sm2)
+ self.p2 = p2 = Package().__of__(sm2)
+
+ sm1.next = getGlobalSiteManager()
+ sm2.next = sm1
+
+ self.unparented_folder = Folder()
+ self.unrooted_subfolder = Folder().__of__(self.unparented_folder)
+ zcml.load_config("meta.zcml", Products.Five)
+ zcml.load_config("permissions.zcml", Products.Five)
+ zcml.load_config("configure.zcml", Products.Five.site)
+ zcml_text = """\
+ <five:localsite
+ xmlns:five="http://namespaces.zope.org/five"
+ class="Products.Five.site.tests.dummy.DummySite" />"""
+ zcml.load_string(zcml_text)
+
+ # Hook up custom component architecture calls; we need to do
+ # this here because zope.app.component.hooks registers a
+ # cleanup with the testing cleanup framework, so the hooks get
+ # torn down by placelesssetup each time.
+ setHooks()
+
+ def test_getSiteManager(self):
+ self.assertEqual(getSiteManager(None), getGlobalSiteManager())
+ self.assertEqual(getSiteManager(self.root), getGlobalSiteManager())
+ self.assertEqual(getSiteManager(self.f1), self.sm1)
+ self.assertEqual(getSiteManager(self.f2), self.sm2)
+ setSite(self.f2)
+ self.assertEqual(getSiteManager(None), self.sm2)
+
+ def test_queryNextSiteManager(self):
+ from zope.app.component import queryNextSiteManager
+ marker = object()
+ self.assert_(queryNextSiteManager(self.root, marker) is marker)
+ self.assert_(queryNextSiteManager(self.f1, marker) is getGlobalSiteManager())
+ #XXX the following used to be
+ #self.assertEqual(queryNextSiteManager(self.f2, marker), marker)
+ self.assertEqual(queryNextSiteManager(self.f2, marker), self.sm1)
+ self.assertEqual(queryNextSiteManager(self.sm1), getGlobalSiteManager())
+ self.assertEqual(queryNextSiteManager(self.sm2), self.sm1)
+ #XXX the following used to be
+ #self.assert_(queryNextSiteManager(self.p1) is getGlobalSiteManager())
+ self.assert_(queryNextSiteManager(self.p1, marker) is marker)
+ #XXX the following used to be
+ #self.assertEqual(queryNextSiteManager(self.p2), self.sm1)
+ self.assert_(queryNextSiteManager(self.p2, marker) is marker)
+
+ self.assert_(queryNextSiteManager(self.unparented_folder, marker)
+ is marker)
+ self.assert_(queryNextSiteManager(self.unrooted_subfolder, marker)
+ is marker)
+
+ def test_getNextSiteManager(self):
+ from zope.app.component import getNextSiteManager
+ self.assertRaises(ComponentLookupError, getNextSiteManager, self.root)
+ self.assertEqual(getNextSiteManager(self.f1), getGlobalSiteManager())
+ #XXX the following used to be
+ #self.assertRaises(ComponentLookupError, getNextSiteManager, self.f2)
+ self.assertEqual(getNextSiteManager(self.f2), self.sm1)
+ self.assertEqual(getNextSiteManager(self.sm1), getGlobalSiteManager())
+ self.assertEqual(getNextSiteManager(self.sm2), self.sm1)
+ #XXX the following used to be
+ #self.assert_(getNextSiteManager(self.p1) is getGlobalSiteManager())
+ self.assertRaises(ComponentLookupError, getNextSiteManager, self.p1)
+ #XXX the following used to be
+ #self.assertEqual(getNextSiteManager(self.p2), self.sm1)
+ self.assertRaises(ComponentLookupError, getNextSiteManager, self.p2)
+
+ self.assertRaises(ComponentLookupError,
+ getNextSiteManager, self.unparented_folder)
+ self.assertRaises(ComponentLookupError,
+ getNextSiteManager, self.unrooted_subfolder)
+
+# XXX Maybe we need to test this with RestrictedPython in the context
+# of Zope2? Maybe we just don't care.
+#
+# def test_getNextSiteManager_security(self):
+# from zope.app.component import getNextSiteManager
+# from zope.security.checker import ProxyFactory, NamesChecker
+# sm = ProxyFactory(self.sm1, NamesChecker(('next',)))
+# # Check that getGlobalSiteManager() is not proxied
+# self.assert_(getNextSiteManager(sm) is getGlobalSiteManager())
+
+ def test_siteManagerAdapter(self):
+ from Products.Five.site.localsite import siteManagerAdapter
+
+ # If it is a site, return the service service.
+ sm = SiteManagerStub()
+ site = Folder()
+ site.setSiteManager(sm)
+ self.assertEqual(siteManagerAdapter(site), sm)
+
+ # If it has an acquisition context, "acquire" the site
+ # and return the service service
+ ob = Folder()
+ ob = ob.__of__(site)
+ self.assertEqual(siteManagerAdapter(ob), sm)
+ ob2 = Folder()
+ ob2 = ob2.__of__(ob)
+ self.assertEqual(siteManagerAdapter(ob2), sm)
+
+ # If it does we are unable to find a service service, raise
+ # ComponentLookupError
+ orphan = Folder()
+ self.failUnless(siteManagerAdapter(orphan) is getGlobalSiteManager())
+
+ def test_setThreadSite_clearThreadSite(self):
+ from zope.app.component.site import threadSiteSubscriber, clearSite
+ from zope.app.publication.zopepublication import BeforeTraverseEvent
+
+ self.assertEqual(getSite(), None)
+
+ # A site is traversed
+ sm = SiteManagerStub()
+ site = Folder()
+ site.setSiteManager(sm)
+
+ ev = BeforeTraverseEvent(site, object())
+ threadSiteSubscriber(site, ev)
+ self.assertEqual(getSite(), site)
+
+ clearSite()
+ self.assertEqual(getSite(), None)
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(SiteManagerTest))
+ return suite
+
+if __name__ == '__main__':
+ framework()
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_localsite.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_sitemanager.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_sitemanager.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_sitemanager.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,28 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
+"""Test Five site manager
+
+$Id$
+"""
+import os, sys
+
+if __name__ == '__main__':
+ execfile(os.path.join(sys.path[0], 'framework.py'))
+
+def test_suite():
+ from Testing.ZopeTestCase import ZopeDocFileSuite
+ return ZopeDocFileSuite('sitemanager.txt', package="Products.Five.site.tests")
+
+if __name__ == '__main__':
+ framework()
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_sitemanager.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_utility.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_utility.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_utility.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,228 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
+"""Test local sites
+
+$Id$
+"""
+import os, sys
+
+if __name__ == '__main__':
+ execfile(os.path.join(sys.path[0], 'framework.py'))
+
+import unittest
+import sets
+from Testing import ZopeTestCase
+
+from zope.interface import directlyProvides
+from zope.component import provideUtility
+from zope.component.exceptions import ComponentLookupError
+from zope.app import zapi
+from zope.app.testing.placelesssetup import setUp, tearDown
+from zope.app.component import getNextUtility
+from zope.app.component.hooks import setSite, clearSite, setHooks
+
+import Products.Five
+from Products.Five import zcml
+from Products.Five.site.interfaces import IRegisterUtilitySimply
+from Products.Five.site.localsite import enableLocalSiteHook
+from Products.Five.site.tests.dummy import manage_addDummySite, \
+ IDummyUtility, ISuperDummyUtility, DummyUtility
+
+class LocalUtilityServiceTest(ZopeTestCase.ZopeTestCase):
+
+ def afterSetUp(self):
+ setUp()
+ zcml.load_config("meta.zcml", Products.Five)
+ zcml.load_config("permissions.zcml", Products.Five)
+ zcml.load_config("configure.zcml", Products.Five.site)
+ zcml_text = """\
+ <five:localsite
+ xmlns:five="http://namespaces.zope.org/five"
+ class="Products.Five.site.tests.dummy.DummySite" />"""
+ zcml.load_string(zcml_text)
+ manage_addDummySite(self.folder, 'site')
+ enableLocalSiteHook(self.folder.site)
+ setSite(self.folder.site)
+
+ # Hook up custom component architecture calls; we need to do
+ # this here because zope.app.component.hooks registers a
+ # cleanup with the testing cleanup framework, so the hooks get
+ # torn down by placelesssetup each time.
+ setHooks()
+
+ def beforeTearDown(self):
+ tearDown()
+
+ def test_getSiteManagerHook(self):
+ from Products.Five.site.localsite import FiveSiteManager
+ from Products.Five.site.utility import SimpleLocalUtilityRegistry
+
+ local_sm = zapi.getSiteManager(None)
+ self.failIf(local_sm is zapi.getGlobalSiteManager())
+ self.failUnless(isinstance(local_sm, FiveSiteManager))
+
+ local_sm = zapi.getSiteManager(self.folder.site)
+ self.failIf(local_sm is zapi.getGlobalSiteManager())
+ self.failUnless(isinstance(local_sm, FiveSiteManager))
+
+ sm = zapi.getSiteManager()
+ self.failUnless(isinstance(sm.utilities, SimpleLocalUtilityRegistry))
+
+ def test_getUtilitiesNoUtilitiesFolder(self):
+ sm = zapi.getSiteManager()
+ #XXX test whether sm really is a local site...
+ self.failUnless(sm.queryUtility(IDummyUtility) is None)
+ self.assertEquals(list(sm.getUtilitiesFor(IDummyUtility)), [])
+ self.assertEquals(list(sm.getAllUtilitiesRegisteredFor(IDummyUtility)), [])
+
+ def test_registerUtilityOnUtilityRegistry(self):
+ utils = zapi.getSiteManager().utilities
+ dummy = DummyUtility()
+ utils.registerUtility(IDummyUtility, dummy, 'dummy')
+
+ self.assertEquals(zapi.getUtility(IDummyUtility, name='dummy'), dummy)
+ self.assertEquals(list(zapi.getUtilitiesFor(IDummyUtility)),
+ [('dummy', dummy)])
+ self.assertEquals(list(zapi.getAllUtilitiesRegisteredFor(
+ IDummyUtility)), [dummy])
+
+ def test_registerUtilityOnSiteManager(self):
+ sm = zapi.getSiteManager()
+ self.failUnless(IRegisterUtilitySimply.providedBy(sm))
+ dummy = DummyUtility()
+ sm.registerUtility(IDummyUtility, dummy, 'dummy')
+
+ self.assertEquals(zapi.getUtility(IDummyUtility, name='dummy'), dummy)
+ self.assertEquals(list(zapi.getUtilitiesFor(IDummyUtility)),
+ [('dummy', dummy)])
+ self.assertEquals(list(zapi.getAllUtilitiesRegisteredFor(
+ IDummyUtility)), [dummy])
+
+ def test_registerTwoUtilitiesWithSameNameDifferentInterface(self):
+ sm = zapi.getSiteManager()
+ self.failUnless(IRegisterUtilitySimply.providedBy(sm))
+ dummy = DummyUtility()
+ superdummy = DummyUtility()
+ directlyProvides(superdummy, ISuperDummyUtility)
+ sm.registerUtility(IDummyUtility, dummy, 'dummy')
+ sm.registerUtility(ISuperDummyUtility, superdummy, 'dummy')
+
+ self.assertEquals(zapi.getUtility(IDummyUtility, 'dummy'), dummy)
+ self.assertEquals(zapi.getUtility(ISuperDummyUtility, 'dummy'),
+ superdummy)
+
+ def test_nestedSitesDontConflictButStillAcquire(self):
+ # let's register a dummy utility in the dummy site
+ dummy = DummyUtility()
+ sm = zapi.getSiteManager()
+ sm.registerUtility(IDummyUtility, dummy)
+
+ # let's also create a subsite and make that our site
+ manage_addDummySite(self.folder.site, 'subsite')
+ enableLocalSiteHook(self.folder.site.subsite)
+ setSite(self.folder.site.subsite)
+
+ # we should still be able to lookup the original utility from
+ # the site one level above
+ self.assertEqual(zapi.getUtility(IDummyUtility), dummy)
+
+ # now we register a dummy utility in the subsite and see that
+ # its registration doesn't conflict
+ subdummy = DummyUtility()
+ sm = zapi.getSiteManager()
+ sm.registerUtility(IDummyUtility, subdummy)
+
+ # when we look it up we get the more local one now because the
+ # more local one shadows the less local one
+ self.assertEqual(zapi.getUtility(IDummyUtility), subdummy)
+
+ # getAllUtilitiesFor gives us both the more local and the less
+ # local utility (XXX not sure if this is the right semantics
+ # for getAllUtilitiesFor)
+ self.assertEqual(sets.Set(zapi.getAllUtilitiesRegisteredFor(IDummyUtility)),
+ sets.Set([subdummy, dummy]))
+
+ # getUtilitiesFor will only find one, because the more local
+ # one shadows the less local one
+ self.assertEqual(list(zapi.getUtilitiesFor(IDummyUtility)),
+ [('', subdummy)])
+
+ def test_registeringTwiceIsConflict(self):
+ dummy1 = DummyUtility()
+ dummy2 = DummyUtility()
+ sm = zapi.getSiteManager()
+ sm.registerUtility(IDummyUtility, dummy1)
+ self.assertRaises(ValueError, sm.registerUtility,
+ IDummyUtility, dummy2)
+
+ sm.registerUtility(IDummyUtility, dummy1, 'dummy')
+ self.assertRaises(ValueError, sm.registerUtility,
+ IDummyUtility, dummy2, 'dummy')
+
+ def test_utilitiesHaveProperAcquisitionContext(self):
+ dummy = DummyUtility()
+ sm = zapi.getSiteManager()
+ sm.registerUtility(IDummyUtility, dummy)
+
+ # let's see if we can acquire something all the way from the
+ # root (Application) object; we need to be careful to choose
+ # something that's only available from the root object
+ from Acquisition import aq_acquire
+ dummy = zapi.getUtility(IDummyUtility)
+ acquired = aq_acquire(dummy, 'ZopeAttributionButton', None)
+ self.failUnless(acquired is not None)
+
+ name, dummy = zapi.getUtilitiesFor(IDummyUtility).next()
+ acquired = aq_acquire(dummy, 'ZopeAttributionButton', None)
+ self.failUnless(acquired is not None)
+
+ dummy = zapi.getAllUtilitiesRegisteredFor(IDummyUtility).next()
+ acquired = aq_acquire(dummy, 'ZopeAttributionButton', None)
+ self.failUnless(acquired is not None)
+
+ def test_getNextUtility(self):
+ # test local site vs. global site
+ global_dummy = DummyUtility()
+ provideUtility(global_dummy, IDummyUtility)
+
+ local_dummy = DummyUtility()
+ sm = zapi.getSiteManager()
+ sm.registerUtility(IDummyUtility, local_dummy)
+
+ self.assertEquals(zapi.getUtility(IDummyUtility), local_dummy)
+ self.assertEquals(getNextUtility(self.folder.site, IDummyUtility),
+ global_dummy)
+
+ # test local site vs. nested local site
+ manage_addDummySite(self.folder.site, 'subsite')
+ enableLocalSiteHook(self.folder.site.subsite)
+ setSite(self.folder.site.subsite)
+
+ sublocal_dummy = DummyUtility()
+ sm = zapi.getSiteManager()
+ sm.registerUtility(IDummyUtility, sublocal_dummy)
+
+ self.assertEquals(zapi.getUtility(IDummyUtility), sublocal_dummy)
+ self.assertEquals(getNextUtility(self.folder.site.subsite, IDummyUtility),
+ local_dummy)
+ self.assertEquals(getNextUtility(self.folder.site, IDummyUtility),
+ global_dummy)
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(LocalUtilityServiceTest))
+ return suite
+
+if __name__ == '__main__':
+ framework()
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/tests/test_utility.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/utility.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/utility.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/utility.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,129 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
+"""Local utility registration
+
+$Id$
+"""
+from zope.interface import implements
+from zope.component import getGlobalSiteManager
+from zope.component.exceptions import ComponentLookupError
+from zope.app.component import getNextSiteManager
+
+from Acquisition import aq_base
+from OFS.Folder import Folder
+from Products.Five.site.interfaces import IFiveUtilityRegistry
+
+class SimpleLocalUtilityRegistry(object):
+ implements(IFiveUtilityRegistry)
+
+ def __init__(self, context):
+ self.context = context
+ # make {get|query}NextSiteManager() work without having to
+ # resort to Zope 2 acquisition
+ self.__parent__ = self.context.getSiteManager()
+
+ @property
+ def next(self):
+ try:
+ return getNextSiteManager(self)
+ except ComponentLookupError:
+ return getGlobalSiteManager()
+
+ def getUtility(self, interface, name=''):
+ """See IFiveUtilityRegistry interface
+ """
+ c = self.queryUtility(interface, name)
+ if c is not None:
+ return c
+ raise ComponentLookupError(interface, name)
+
+ def queryUtility(self, interface, name='', default=None):
+ """See IFiveUtilityRegistry interface
+ """
+ if name == '':
+ # Singletons. Only one per interface allowed, so, let's call it
+ # by the interface.
+ id = interface.getName()
+ else:
+ id = interface.getName() + '-' + name
+
+ if getattr(aq_base(self.context), 'utilities', None) is not None:
+ utility = self.context.utilities._getOb(id, None)
+ if utility is not None:
+ return utility
+ return self.next.queryUtility(interface, name, default)
+
+ def getUtilitiesFor(self, interface):
+ names = []
+ prefix = interface.getName() + '-'
+ if getattr(aq_base(self.context), 'utilities', None) is not None:
+ for name, utility in self.context.utilities.objectItems():
+ if name == interface.getName():
+ names.append('')
+ yield '', utility
+ elif name.startswith(prefix):
+ name = name[len(prefix):]
+ names.append(name)
+ yield (name, utility)
+ for name, utility in self.next.getUtilitiesFor(interface):
+ if name not in names:
+ yield name, utility
+
+ def getAllUtilitiesRegisteredFor(self, interface):
+ # This also supposedly returns "overridden" utilities, but we don't
+ # keep them around. It also does not return the name-value pair that
+ # getUtilitiesFor returns.
+ if getattr(aq_base(self.context), 'utilities', None) is not None:
+ for utility in self.context.utilities.objectValues():
+ if interface.providedBy(utility):
+ yield utility
+ for utility in self.next.getAllUtilitiesRegisteredFor(interface):
+ yield utility
+
+ def registerUtility(self, interface, utility, name=''):
+ # I think you are *really* supposed to:
+ # 1. Check if there is a "registrations" object for utilities.
+ # 2. If not create one.
+ # 3. Get it.
+ # 4. Create a registration object for the utility.
+ # 5. Rgister the registration object in the registrations.
+ # But that is quite complex, and Jim sais he wants to change that
+ # anyway, and in any case the way you would normally do this in Zope3
+ # and Five would probably differ anyway, so, here is this new
+ # Five-only, easy to use method!
+
+ if getattr(aq_base(self.context), 'utilities', None) is None:
+ self.context._setObject('utilities', Folder('utilities'))
+ utilities = self.context.utilities
+
+ if name == '':
+ # Singletons. Only one per interface allowed, so, let's call it
+ # by the interface.
+ id = interface.getName()
+ else:
+ id = interface.getName() + '-' + name
+
+ if id in utilities.objectIds():
+ raise ValueError("There is already a utility registered for "
+ "%s with the name '%s'" % (interface.getName(),
+ name))
+ utilities._setObject(id, utility)
+
+# BBB 2005/11/01 -- gone in Five 1.5.
+SimpleLocalUtilityService = SimpleLocalUtilityRegistry
+import zope.deprecation
+zope.deprecation.deprecated(
+ 'SimpleLocalUtilityService', "'SimpleLocalUtilityService' has been renamed to "
+ "'SimpleLocalUtilityRegistry' and will disappear in Five 1.5."
+ )
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/site/utility.py
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/skin/standardmacros.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/skin/standardmacros.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/skin/standardmacros.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -13,17 +13,17 @@
##############################################################################
"""Mimick the Zope 3 skinning system in Five.
-$Id: standardmacros.py 12884 2005-05-30 13:10:41Z philikon $
+$Id: standardmacros.py 19283 2005-10-31 17:43:51Z philikon $
"""
-from zope.interface.common.mapping import IItemMapping
-from zope.interface import implements
-from zope.component import getView
+import zope.interface
+
+from zope.app import zapi
from Products.Five.browser import BrowserView
# this is a verbatim copy of zope.app.basicskin except that it doesn't
# derive from ``object``
class Macros:
- implements(IItemMapping)
+ zope.interface.implements(zope.interface.common.mapping.IItemMapping)
macro_pages = ()
aliases = {
@@ -37,7 +37,7 @@
context = self.context
request = self.request
for name in self.macro_pages:
- page = getView(context, name, request)
+ page = zapi.getMultiAdapter((context, request), name=name)
try:
v = page[key]
except KeyError:
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/skin/tests/test_standardmacros.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/skin/tests/test_standardmacros.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/skin/tests/test_standardmacros.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -26,7 +26,7 @@
>>> uf._doAddUser('manager', 'r00t', ['Manager'], [])
>>> self.login('manager')
- >>> from Products.Five.testing import manage_addFiveTraversableFolder
+ >>> from Products.Five.tests.testing import manage_addFiveTraversableFolder
>>> manage_addFiveTraversableFolder(self.folder, 'testoid', 'Testoid')
>>> import Products.Five.skin.tests
@@ -72,7 +72,7 @@
Clean up:
- >>> from zope.app.tests.placelesssetup import tearDown
+ >>> from zope.app.testing.placelesssetup import tearDown
>>> tearDown()
"""
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/README.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/README.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/README.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -1,16 +1,8 @@
Five tests
==========
-The tests require ZopeTestCase to be installed. ZopeTestCase can be
-downloaded from here:
+All you have to do is type::
-http://zope.org/Members/shh/ZopeTestCase
+ $ bin/zopectl test -s Products.Five
-it needs to be installed in your Zope software's lib/python/Testing
-directory.
-
-Then, if you have Zope 2.7.3 or better all you have to do is type::
-
- ./bin/zopectl test --dir Products/Five
-
-to run the Five tests.
+to run the Five tests.
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/boilerplate.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/boilerplate.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/boilerplate.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -21,16 +21,16 @@
def test_boilerplate():
"""
- >>> from zope.app.tests.placelesssetup import setUp, tearDown
+ >>> from zope.app.testing.placelesssetup import setUp, tearDown
>>> setUp()
>>> import Products.Five.tests
>>> from Products.Five import zcml
>>> zcml.load_config('boilerplate.zcml', Products.Five.tests)
- >>> from Products.Five.testing import manage_addFiveTraversableFolder
- >>> from Products.Five.testing.simplecontent import manage_addSimpleContent
- >>> from Products.Five.testing.fancycontent import manage_addFancyContent
+ >>> from Products.Five.tests.testing import manage_addFiveTraversableFolder
+ >>> from Products.Five.tests.testing.simplecontent import manage_addSimpleContent
+ >>> from Products.Five.tests.testing.fancycontent import manage_addFancyContent
>>> tearDown()
"""
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/directives.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/directives.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/directives.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -11,17 +11,17 @@
once on a class; SimpleContent inherits from Traversable, so
one directive suffices here -->
- <five:traversable class="Products.Five.testing.simplecontent.SimpleContent" />
+ <five:traversable class="Products.Five.tests.testing.simplecontent.SimpleContent" />
<!-- this is a test whether the *directive* can be called more than
once without raising a conflicting configuration exception -->
- <five:traversable class="Products.Five.testing.simplecontent.SimpleContent" />
+ <five:traversable class="Products.Five.tests.testing.simplecontent.SimpleContent" />
<!-- this tests whether five:traversable can be called on a class that
already provides __bobo_traverse__, such as our FancyContent -->
- <five:traversable class="Products.Five.testing.fancycontent.FancyContent" />
+ <five:traversable class="Products.Five.tests.testing.fancycontent.FancyContent" />
<!-- Testing the vocabulary directive -->
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/event.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/event.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/event.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -1,295 +1,394 @@
-Test events
-===========
+================
+Container events
+================
-Before we can start, we need to set up an event subscriber that allows
-us to inspect events that will be thrown during the test:
+Zope 3 container events are used to inform subscribers that an object is
+about to be added/removed from a container, and also after it has been
+done. This is used for bookkeeping and cleaning up in subobjects.
- >>> from zope.app.tests.placelesssetup import setUp, tearDown
- >>> setUp()
+These events replace the old Zope 2 manage_afterAdd, manage_beforeDelete
+and manage_afterClone methods.
-Add a folder that doesn't verify objects on paste. We use it as a
-test sandbox:
+All standard Zope containers will only call manage_afterAdd & co on
+classes specified with the directive::
- >>> from Products.Five.testing import manage_addNoVerifyPasteFolder
- >>> manage_addNoVerifyPasteFolder(self.folder, 'npvf')
- >>> folder = self.folder.npvf
+ <five:deprecatedManageAddDelete class="some.content.class"/>
-Finally add a manager user login, give it the right permissions and
-log in using it:
+Classes that don't have this directive but still have manage_afterAdd &
+co methods will trigger a warning when they are called (and this is
+strictly a compatibility call, behavior may not be strictly equivalent
+to the original one).
- >>> uf = self.folder.acl_users
- >>> uf._doAddUser('manager', 'r00t', ['Manager'], [])
- >>> self.setPermissions(standard_permissions + ['Copy or Move'], 'Manager')
- >>> self.login('manager')
+Test setup
+==========
- >>> from zope.app.event.tests.placelesssetup import getEvents, clearEvents
+A bit of setup for the tests. Because we'll test copy/paste, we need to
+work inside a database::
+ >>> from zope.app.testing.placelesssetup import setUp, tearDown
+ >>> setUp()
-Sending events
---------------
+ >>> import ZODB.tests.util
+ >>> db = ZODB.tests.util.DB()
+ >>> connection = db.open()
+ >>> root = connection.root()
-Zope 2 classes need to be modified so that they send Zope 3 style
-events. Our stub class here is such a case. We can add it to a
-folder, for example, ...
+We'll use a few simple classes (defined in python code for picklability)
+for our tests.
- >>> from Products.Five.testing.simplecontent import manage_addSimpleContent
- >>> manage_addSimpleContent(folder, 'foo', 'Foo')
+ >>> from Products.Five.tests.test_event import MyApp, MyContent
+ >>> from Products.Five.tests.test_event import MyFolder, MyBTreeFolder
+ >>> from Products.Five.tests.test_event import MyOrderedFolder
-and no event will have been triggered:
+ >>> app = MyApp('')
+ >>> root['app'] = app
+ >>> folder = MyFolder('folder')
+ >>> app._setObject('folder', folder) # doctest: +NORMALIZE_WHITESPACE
+ old manage_afterAdd folder folder
+ 'folder'
+ >>> folder = app.folder
+ >>> btfolder = MyBTreeFolder('btfolder')
+ >>> app._setObject('btfolder', btfolder) # doctest: +NORMALIZE_WHITESPACE
+ old manage_afterAdd btfolder btfolder
+ 'btfolder'
- >>> len(getEvents())
- 0
+To observe what object events are dispatched, we'll have some
+subscribers print them. We'll actually do that for a specific interface,
+not for (None, IObjectEvent), and register our subscribers before the
+framework's ones, so ours will be called first. This has the effect that
+printed events will be in their "natural" order::
-Clean up:
+ >>> from zope.app.event.interfaces import IObjectEvent
+ >>> from zope.app.container.interfaces import IObjectMovedEvent
+ >>> from OFS.interfaces import IObjectWillBeMovedEvent
+ >>> from OFS.interfaces import IObjectClonedEvent
+ >>> from OFS.interfaces import IItem
+ >>> def printObjectEvent(object, event):
+ ... print event.__class__.__name__, object.getId()
+ >>> def printObjectEventExceptSome(object, event):
+ ... if (IObjectMovedEvent.providedBy(event) or
+ ... IObjectWillBeMovedEvent.providedBy(event) or
+ ... IObjectClonedEvent.providedBy(event)):
+ ... return
+ ... print event.__class__.__name__, object.getId()
- >>> folder.manage_delObjects(['foo'])
+ >>> from zope.component import provideHandler
+ >>> provideHandler(printObjectEvent, (IItem, IObjectMovedEvent))
+ >>> provideHandler(printObjectEvent, (IItem, IObjectWillBeMovedEvent))
+ >>> provideHandler(printObjectEvent, (IItem, IObjectClonedEvent))
+ >>> provideHandler(printObjectEventExceptSome, (None, IObjectEvent))
-Now make the class send events:
+Finally we need to load the subscribers configuration::
- >>> from Products.Five.eventconfigure import classSendEvents
- >>> from Products.Five.testing.simplecontent import SimpleContent
- >>> classSendEvents(SimpleContent)
+ >>> from Products.Five import zcml
+ >>> import Products.Five
+ >>> import zope.app.component
+ >>> zcml.load_config('meta.zcml', zope.app.component)
+ >>> zcml.load_config('event.zcml', Products.Five)
+Old class
+=========
-Added event
-------------
+If we use an instance of an old class for which we haven't specified
+anything, events are sent and the manage_afterAdd & co methods are
+called but in a "compatibility" way.
-Let's add an object to a folder:
+Because the bases classes of Zope have been changed to not recurse
+except through the event framework, unexpected behavior may happen
+(however a warning will be sent)::
- >>> manage_addSimpleContent(folder, 'foo', 'Foo')
+ >>> ob = MyContent('dog')
+ >>> folder._setObject('dog', ob)
+ ObjectWillBeAddedEvent dog
+ ObjectAddedEvent dog
+ old manage_afterAdd dog dog folder
+ 'dog'
-One object event should have been sent with the event's object being
-our foo object:
+And when we delete the object, manage_beforeDelete is also called and
+events are sent::
- >>> events = getEvents()
- >>> len(events)
- 1
- >>> foo = folder.foo
- >>> events[0].object == foo
- True
+ >>> folder.manage_delObjects('dog')
+ old manage_beforeDelete dog dog folder
+ ObjectWillBeRemovedEvent dog
+ ObjectRemovedEvent dog
-That object event should have been an object added event:
+Old class with deprecatedManageAddDelete
+========================================
- >>> from zope.app.container.interfaces import IObjectAddedEvent
- >>> events = getEvents(IObjectAddedEvent)
- >>> len(events)
- 1
- >>> events[0].object == foo
- True
- >>> events[0].newParent == foo.aq_parent
- True
+We specifiy that our class is deprecated (using zcml in real life)::
-Check that the object's original manage_afterAdd method was also called:
+ >>> from Products.Five.eventconfigure import setDeprecatedManageAddDelete
+ >>> setDeprecatedManageAddDelete(MyContent)
+ >>> setDeprecatedManageAddDelete(MyFolder)
+ >>> setDeprecatedManageAddDelete(MyOrderedFolder)
- >>> foo.afterAdd_called
- True
+Now some events are sent but the old manage_afterAdd method is also
+called correctly::
-Now clean up:
+ >>> ob = MyContent('lassie')
+ >>> folder._setObject('lassie', ob)
+ ObjectWillBeAddedEvent lassie
+ ObjectAddedEvent lassie
+ old manage_afterAdd lassie lassie folder
+ 'lassie'
- >>> clearEvents()
+And when we delete the object, manage_beforeDelete is also called and
+events are sent::
+ >>> folder.manage_delObjects('lassie')
+ ObjectWillBeRemovedEvent lassie
+ old manage_beforeDelete lassie lassie folder
+ ObjectRemovedEvent lassie
-Moved event (I) -- Renaming
---------------------------
+The old behavior happens for a move or a copy, with events too.
+For a move::
-Somehow we need to at least commit a subtransaction to make renaming
-succeed:
+ >>> ob = MyContent('blueberry')
+ >>> folder._setObject('blueberry', ob)
+ ObjectWillBeAddedEvent blueberry
+ ObjectAddedEvent blueberry
+ old manage_afterAdd blueberry blueberry folder
+ 'blueberry'
+ >>> cp = folder.manage_cutObjects('blueberry')
+ >>> folder.manage_pasteObjects(cp)
+ ObjectWillBeMovedEvent blueberry
+ old manage_beforeDelete blueberry blueberry folder
+ ObjectMovedEvent blueberry
+ old manage_afterAdd blueberry blueberry folder
+ [{'new_id': 'blueberry', 'id': 'blueberry'}]
- >>> import transaction
- >>> transaction.commit(1)
+Old behavior with events for a copy::
-Let's rename the object we created before:
+ >>> cp = folder.manage_copyObjects('blueberry')
+ >>> folder.manage_pasteObjects(cp)
+ ObjectCopiedEvent copy_of_blueberry
+ ObjectWillBeAddedEvent copy_of_blueberry
+ ObjectAddedEvent copy_of_blueberry
+ old manage_afterAdd copy_of_blueberry copy_of_blueberry folder
+ ObjectClonedEvent copy_of_blueberry
+ old manage_afterClone copy_of_blueberry copy_of_blueberry
+ [{'new_id': 'copy_of_blueberry', 'id': 'blueberry'}]
- >>> folder.manage_renameObject('foo', 'bar')
+Old behavior with events for a renaming::
-We should get two events...
+ >>> folder.manage_renameObject('copy_of_blueberry', 'myrtille')
+ ObjectWillBeMovedEvent copy_of_blueberry
+ old manage_beforeDelete copy_of_blueberry copy_of_blueberry folder
+ ObjectMovedEvent myrtille
+ old manage_afterAdd myrtille myrtille folder
- >>> events = getEvents()
- >>> len(events)
- 2
+Old behavior with events for a clone::
-the removed event...
+ >>> res = folder.manage_clone(folder.blueberry, 'strawberry')
+ ObjectCopiedEvent strawberry
+ ObjectWillBeAddedEvent strawberry
+ ObjectAddedEvent strawberry
+ old manage_afterAdd strawberry strawberry folder
+ ObjectClonedEvent strawberry
+ old manage_afterClone strawberry strawberry
+ >>> res.getId()
+ 'strawberry'
- >>> event = events[0]
- >>> from zope.app.container.interfaces import IObjectRemovedEvent
- >>> IObjectRemovedEvent.providedBy(event)
- True
- >>> event.object == foo
- True
- >>> event.oldName, event.newName
- ('foo', None)
- >>> event.oldParent == folder
- True
- >>> event.newParent is None
- True
+Events are also sent when we work with a BTreeFolder::
-and the moved event:
+ >>> ob = MyContent('luckyluke')
+ >>> btfolder._setObject('luckyluke', ob)
+ ObjectWillBeAddedEvent luckyluke
+ ObjectAddedEvent luckyluke
+ old manage_afterAdd luckyluke luckyluke btfolder
+ 'luckyluke'
- >>> event = events[1]
- >>> event.object == foo
- True
- >>> event.oldName, event.newName
- ('foo', 'bar')
- >>> event.oldParent == folder
- True
- >>> event.newParent == folder
- True
+ >>> btfolder.manage_delObjects('luckyluke')
+ ObjectWillBeRemovedEvent luckyluke
+ old manage_beforeDelete luckyluke luckyluke btfolder
+ ObjectRemovedEvent luckyluke
-Now clean up:
+Here is what happens for a tree of objects. Let's create a simple one::
- >>> folder.manage_delObjects(['bar'])
- >>> clearEvents()
+ >>> subfolder = MyFolder('subfolder')
+ >>> folder._setObject('subfolder', subfolder)
+ ObjectWillBeAddedEvent subfolder
+ ObjectAddedEvent subfolder
+ old manage_afterAdd subfolder subfolder folder
+ 'subfolder'
+ >>> subfolder = folder.subfolder
+ >>> ob = MyContent('donald')
+ >>> subfolder._setObject('donald', ob)
+ ObjectWillBeAddedEvent donald
+ ObjectAddedEvent donald
+ old manage_afterAdd donald donald subfolder
+ 'donald'
-We don't delete the stub object just yet because it's being used in
-the next part of the test.
+Renaming a tree of objects. Note that manage_beforeDelete is called
+bottom-up::
+ >>> folder.manage_renameObject('subfolder', 'pluto')
+ ObjectWillBeMovedEvent subfolder
+ ObjectWillBeMovedEvent donald
+ old manage_beforeDelete donald subfolder folder
+ old manage_beforeDelete subfolder subfolder folder
+ ObjectMovedEvent pluto
+ old manage_afterAdd pluto pluto folder
+ ObjectMovedEvent donald
+ old manage_afterAdd donald pluto folder
-Moved event (II) -- Cut and paste
----------------------------------
+Cloning a tree of objects::
-Let's move from one folder to another:
+ >>> res = folder.manage_clone(folder.pluto, 'mickey')
+ ObjectCopiedEvent mickey
+ ObjectWillBeAddedEvent mickey
+ ObjectWillBeAddedEvent donald
+ ObjectAddedEvent mickey
+ old manage_afterAdd mickey mickey folder
+ ObjectAddedEvent donald
+ old manage_afterAdd donald mickey folder
+ ObjectClonedEvent mickey
+ old manage_afterClone mickey mickey
+ ObjectClonedEvent donald
+ old manage_afterClone donald mickey
+ >>> res.getId()
+ 'mickey'
- >>> manage_addNoVerifyPasteFolder(folder, 'folder1', 'Folder1')
- >>> folder1 = folder.folder1
- >>> manage_addNoVerifyPasteFolder(folder, 'folder2', 'Folder2')
- >>> folder2 = folder.folder2
- >>> manage_addSimpleContent(folder1, 'foo', 'Foo')
- >>> foo = folder1.foo
+New class
+=========
-We need to trigger a subtransaction before cut/paste can work:
+If we use classes that don't have any manage_afterAdd & co method,
+everything happens correctly::
- >>> transaction.commit(1)
- >>> cb = folder1.manage_cutObjects(['foo'])
- >>> info = folder2.manage_pasteObjects(cb)
+ >>> from Products.Five.tests.test_event import MyNewFolder, MyNewContent
+ >>> app = MyApp('')
+ >>> root['app'] = app
+ >>> folder = MyNewFolder('folder')
+ >>> app._setObject('folder', folder)
+ ObjectWillBeAddedEvent folder
+ ObjectAddedEvent folder
+ 'folder'
+ >>> folder = app.folder
-Apart from the added event we triggerred when we added the stub object
-to the folder, we expect two events...
+ >>> ob = MyNewContent('dogbert')
+ >>> folder._setObject('dogbert', ob)
+ ObjectWillBeAddedEvent dogbert
+ ObjectAddedEvent dogbert
+ 'dogbert'
+ >>> folder.manage_delObjects('dogbert')
+ ObjectWillBeRemovedEvent dogbert
+ ObjectRemovedEvent dogbert
- >>> events = getEvents()
- >>> len(events)
- 3
- >>> len(getEvents(IObjectAddedEvent))
- 1
+Now move::
-a removed event...
+ >>> ob = MyNewContent('dilbert')
+ >>> folder._setObject('dilbert', ob)
+ ObjectWillBeAddedEvent dilbert
+ ObjectAddedEvent dilbert
+ 'dilbert'
+ >>> cp = folder.manage_cutObjects('dilbert')
+ >>> folder.manage_pasteObjects(cp)
+ ObjectWillBeMovedEvent dilbert
+ ObjectMovedEvent dilbert
+ [{'new_id': 'dilbert', 'id': 'dilbert'}]
- >>> event = events[1]
- >>> from zope.app.container.interfaces import IObjectRemovedEvent
- >>> IObjectRemovedEvent.providedBy(event)
- True
- >>> event.oldParent == folder1
- True
- >>> event.newParent is None
- True
+And copy::
-and a moved event:
+ >>> cp = folder.manage_copyObjects('dilbert')
+ >>> folder.manage_pasteObjects(cp)
+ ObjectCopiedEvent copy_of_dilbert
+ ObjectWillBeAddedEvent copy_of_dilbert
+ ObjectAddedEvent copy_of_dilbert
+ ObjectClonedEvent copy_of_dilbert
+ [{'new_id': 'copy_of_dilbert', 'id': 'dilbert'}]
- >>> event = events[2]
- >>> event.object == foo
- True
- >>> event.oldName, event.newName
- ('foo', 'foo')
- >>> event.oldParent == folder1
- True
- >>> event.newParent == folder2
- True
+Then rename::
-Now clean up:
+ >>> folder.manage_renameObject('copy_of_dilbert', 'wally')
+ ObjectWillBeMovedEvent copy_of_dilbert
+ ObjectMovedEvent wally
- >>> folder.manage_delObjects(['folder1'])
- >>> folder.manage_delObjects(['folder2'])
- >>> clearEvents()
+Or copy using manage_clone::
+ >>> res = folder.manage_clone(folder.dilbert, 'phb')
+ ObjectCopiedEvent phb
+ ObjectWillBeAddedEvent phb
+ ObjectAddedEvent phb
+ ObjectClonedEvent phb
+ >>> res.getId()
+ 'phb'
-Copied event
-------------
+Also on a BTreeFolder::
- >>> manage_addSimpleContent(folder, 'foo', 'Foo')
- >>> manage_addNoVerifyPasteFolder(folder, 'folder1')
- >>> folder1 = folder.folder1
+ >>> ob = MyNewContent('alice')
+ >>> btfolder._setObject('alice', ob)
+ ObjectWillBeAddedEvent alice
+ ObjectAddedEvent alice
+ 'alice'
+ >>> btfolder.manage_renameObject('alice', 'rabbit')
+ ObjectWillBeMovedEvent alice
+ ObjectMovedEvent rabbit
+ >>> btfolder.manage_delObjects('rabbit')
+ ObjectWillBeRemovedEvent rabbit
+ ObjectRemovedEvent rabbit
-We need to trigger subtransaction before copy/paste can work
+Now for a tree of objects. Let's create a simple one::
- >>> transaction.commit(1)
- >>> cb = folder.manage_copyObjects(['foo'])
- >>> info = folder1.manage_pasteObjects(cb)
- >>> foo = folder1.foo
+ >>> subfolder = MyNewFolder('subfolder')
+ >>> folder._setObject('subfolder', subfolder)
+ ObjectWillBeAddedEvent subfolder
+ ObjectAddedEvent subfolder
+ 'subfolder'
+ >>> subfolder = folder.subfolder
+ >>> ob = MyNewContent('mel')
+ >>> subfolder._setObject('mel', ob)
+ ObjectWillBeAddedEvent mel
+ ObjectAddedEvent mel
+ 'mel'
-Apart from the added event we triggerred when we added the stub object
-to the folder, we expect two events...
+Renaming a tree of objects::
- >>> events = getEvents()
- >>> len(events)
- 3
+ >>> folder.manage_renameObject('subfolder', 'firefly')
+ ObjectWillBeMovedEvent subfolder
+ ObjectWillBeMovedEvent mel
+ ObjectMovedEvent firefly
+ ObjectMovedEvent mel
-a copied event...
+Cloning a tree of objects::
- >>> event = events[1]
- >>> from zope.app.event.interfaces import IObjectCopiedEvent
- >>> IObjectCopiedEvent.providedBy(event)
- True
- >>> events[1].object == foo
- True
+ >>> res = folder.manage_clone(folder.firefly, 'serenity')
+ ObjectCopiedEvent serenity
+ ObjectWillBeAddedEvent serenity
+ ObjectWillBeAddedEvent mel
+ ObjectAddedEvent serenity
+ ObjectAddedEvent mel
+ ObjectClonedEvent serenity
+ ObjectClonedEvent mel
+ >>> res.getId()
+ 'serenity'
-and an added event:
+OrderedFolder has the same renaming behavior than before::
- >>> event = events[2]
- >>> IObjectAddedEvent.providedBy(event)
- True
- >>> event.object == foo
- True
- >>> event.newName
- 'foo'
- >>> event.newParent == folder1
- True
+ >>> ofolder = MyOrderedFolder('ofolder')
+ >>> app._setObject('ofolder', ofolder) # doctest: +NORMALIZE_WHITESPACE
+ ObjectWillBeAddedEvent ofolder
+ ObjectAddedEvent ofolder
+ old manage_afterAdd ofolder ofolder
+ 'ofolder'
+ >>> ob1 = MyNewContent('ob1')
+ >>> ofolder._setObject('ob1', ob1)
+ ObjectWillBeAddedEvent ob1
+ ObjectAddedEvent ob1
+ 'ob1'
+ >>> ob2 = MyNewContent('ob2')
+ >>> ofolder._setObject('ob2', ob2)
+ ObjectWillBeAddedEvent ob2
+ ObjectAddedEvent ob2
+ 'ob2'
+ >>> ofolder.manage_renameObject('ob1', 'ob4')
+ ObjectWillBeMovedEvent ob1
+ ObjectMovedEvent ob4
+ >>> ofolder.objectIds()
+ ['ob4', 'ob2']
-Now clean up:
- >>> folder.manage_delObjects(['folder1'])
- >>> folder.manage_delObjects(['foo'])
- >>> clearEvents()
+Now cleanup::
-
-Removed event
--------------
-
- >>> manage_addSimpleContent(folder, 'foo', 'Foo')
- >>> foo = folder.foo
- >>> foo.beforeDelete_called
- False
- >>> folder.manage_delObjects(['foo'])
-
- >>> events = getEvents()
- >>> len(events)
- 2
-
- >>> events[1].object.id
- 'foo'
-
-Check that the object's original manage_beforeDelete method was also called:
-
- >>> foo.beforeDelete_called
- True
-
- >>> clearEvents()
-
-
-Clean up
---------
-
-Finally, we need to put our stub class back the way it was before we
-monkeyed with it:
-
- >>> from Products.Five.eventconfigure import cleanUp
- >>> cleanUp()
-
-Now adding an object won't trigger an event anymore:
-
- >>> from Products.Five.testing.simplecontent import manage_addSimpleContent
- >>> manage_addSimpleContent(folder, 'foo', 'Foo')
- >>> len(getEvents())
- 0
-
-Finally, we need to tear down everything else (services, etc.)
-
+ >>> import transaction
+ >>> transaction.abort()
>>> tearDown()
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_directives.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_directives.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_directives.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -23,9 +23,6 @@
"""
Test ZCML directives
- >>> from zope.app.tests.placelesssetup import setUp, tearDown
- >>> setUp()
-
There isn't much to test here since the actual directive handlers
are either tested in other, more specific tests, or they're
already tested in Zope 3. We'll just do a symbolic test of
@@ -62,9 +59,10 @@
>>> dest.method()
'Overridden'
- Clean up:
+ Clean up adapter registry and others:
- >>> tearDown()
+ >>> from zope.testing.cleanup import cleanUp
+ >>> cleanUp()
"""
def test_suite():
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_event.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_event.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_event.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -19,9 +19,64 @@
if __name__ == '__main__':
execfile(os.path.join(sys.path[0], 'framework.py'))
+
+# These classes aren't defined in the doctest because otherwise
+# they wouldn't be picklable, and we need that to test copy/paste.
+
+from OFS.SimpleItem import SimpleItem
+from OFS.Folder import Folder
+from OFS.OrderedFolder import OrderedFolder
+from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2
+
+class DontComplain(object):
+ def _verifyObjectPaste(self, object, validate_src=1):
+ pass
+ def cb_isMoveable(self):
+ return True
+ def cb_isCopyable(self):
+ return True
+
+class NotifyBase(DontComplain):
+ def manage_afterAdd(self, item, container):
+ print 'old manage_afterAdd %s %s %s' % (self.getId(), item.getId(),
+ container.getId())
+ def manage_beforeDelete(self, item, container):
+ print 'old manage_beforeDelete %s %s %s' % (self.getId(), item.getId(),
+ container.getId())
+ def manage_afterClone(self, item):
+ print 'old manage_afterClone %s %s' % (self.getId(), item.getId())
+
+class MyApp(Folder):
+ def getPhysicalRoot(self):
+ return self
+
+class MyFolder(NotifyBase, Folder):
+ pass
+
+class MyOrderedFolder(NotifyBase, OrderedFolder):
+ pass
+
+class MyBTreeFolder(NotifyBase, BTreeFolder2):
+ def _verifyObjectPaste(self, object, validate_src=1):
+ pass
+
+class MyContent(NotifyBase, SimpleItem):
+ def __init__(self, id):
+ self._setId(id)
+
+# These don't have manage_beforeDelete & co methods
+
+class MyNewContent(DontComplain, SimpleItem):
+ def __init__(self, id):
+ self._setId(id)
+
+class MyNewFolder(DontComplain, Folder):
+ pass
+
+
def test_suite():
- from Testing.ZopeTestCase import ZopeDocFileSuite
- return ZopeDocFileSuite('event.txt', package="Products.Five.tests")
+ from zope.testing.doctest import DocFileSuite
+ return DocFileSuite('event.txt', package="Products.Five.tests")
if __name__ == '__main__':
framework()
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_i18n.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_i18n.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_i18n.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -23,7 +23,7 @@
"""
Test the i18n directive
- >>> from zope.app.tests.placelesssetup import setUp, tearDown
+ >>> from zope.app.testing.placelesssetup import setUp, tearDown
>>> setUp()
First, we need to register the ZCML directive:
@@ -44,9 +44,9 @@
Now, take an arbitrary message id from that domain:
- >>> from zope.i18nmessageid import MessageIDFactory
+ >>> from zope.i18nmessageid import MessageFactory
>>> from zope.i18n import translate
- >>> _ = MessageIDFactory('fivetest')
+ >>> _ = MessageFactory('fivetest')
>>> msg = _(u'explicit-msg', u'This is an explicit message')
As you can see, both the default functionality and translation to
Deleted: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_import_conflicts.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_import_conflicts.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_import_conflicts.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -1,40 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004, 2005 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.
-#
-##############################################################################
-"""Test import conflicts
-
-$Id: test_import_conflicts.py 18150 2005-10-04 16:19:49Z philikon $
-"""
-import os, sys
-if __name__ == '__main__':
- execfile(os.path.join(sys.path[0], 'framework.py'))
-
-def testImportConflicts():
- """
- In a Five environment, importing Zope 3 packages that would use
- interfaces from the Zope 3 transaction module would lead to an
- error, because of the monkey patching. The zope.app.mail package
- makes use of transaction interfaces, for example the following
- class:
-
- >>> from zope.app.mail.delivery import QueueProcessorThread
-
- Note that this only concerns Zope 2.7 and Zope X3 3.0.
- """
-
-def test_suite():
- from Testing.ZopeTestCase import ZopeDocTestSuite
- return ZopeDocTestSuite()
-
-if __name__ == '__main__':
- framework()
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_registerclass.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_registerclass.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_registerclass.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,151 @@
+##############################################################################
+#
+# Copyright (c) 2004, 2005 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.
+#
+##############################################################################
+"""Unit tests for the registerClass directive.
+
+$Id$
+"""
+import os, sys
+if __name__ == '__main__':
+ execfile(os.path.join(sys.path[0], 'framework.py'))
+
+def test_registerClass():
+ """
+ Testing registerClass
+
+ >>> from zope.app.testing.placelesssetup import setUp, tearDown
+ >>> setUp()
+ >>> import Products
+ >>> import Products.Five
+ >>> from Products.Five import zcml
+ >>> from Products.Five.tests.testing.simplecontent import SimpleContent
+ >>> from Products.Five.tests.testing.simplecontent import ISimpleContent
+ >>> from persistent.interfaces import IPersistent
+
+ Use the five:registerClass directive::
+
+ >>> configure_zcml = '''
+ ... <configure
+ ... xmlns="http://namespaces.zope.org/zope"
+ ... xmlns:five="http://namespaces.zope.org/five"
+ ... i18n_domain="foo">
+ ... <permission id="foo.add" title="Add Foo"/>
+ ... <five:registerClass
+ ... class="Products.Five.tests.testing.simplecontent.SimpleContent"
+ ... meta_type="Foo Type"
+ ... permission="foo.add"
+ ... addview="addfoo.html"
+ ... icon="foo_icon.png"
+ ... global="false"
+ ... />
+ ... </configure>'''
+ >>> zcml.load_config('meta.zcml', Products.Five)
+ >>> zcml.load_string(configure_zcml)
+
+ Make sure that the class attributes are set correctly::
+
+ >>> SimpleContent.meta_type
+ 'Foo Type'
+ >>> SimpleContent.icon
+ '++resource++foo_icon.png'
+
+ And the meta_type is registered correctly::
+
+ >>> for info in Products.meta_types:
+ ... if info['name'] == 'Foo Type':
+ ... break
+ >>> info['product']
+ 'Five'
+ >>> info['permission']
+ 'Add Foo'
+ >>> ISimpleContent in info['interfaces']
+ True
+ >>> IPersistent in info['interfaces']
+ True
+ >>> info['visibility'] is None
+ True
+ >>> info['instance'] is SimpleContent
+ True
+ >>> info['action']
+ '+/addfoo.html'
+ >>> info['container_filter'] is None
+ True
+
+ Now reset everything and see what happens without optional parameters::
+
+ >>> tearDown()
+ >>> setUp()
+
+ Use the five:registerClass directive again::
+
+ >>> configure_zcml = '''
+ ... <configure
+ ... xmlns="http://namespaces.zope.org/zope"
+ ... xmlns:five="http://namespaces.zope.org/five"
+ ... i18n_domain="bar">
+ ... <permission id="bar.add" title="Add Bar"/>
+ ... <five:registerClass
+ ... class="Products.Five.tests.testing.simplecontent.SimpleContent"
+ ... meta_type="Bar Type"
+ ... permission="bar.add"
+ ... />
+ ... </configure>'''
+ >>> zcml.load_config('meta.zcml', Products.Five)
+ >>> zcml.load_string(configure_zcml)
+
+ Make sure that the class attributes are set correctly::
+
+ >>> SimpleContent.meta_type
+ 'Bar Type'
+ >>> SimpleContent.icon
+ ''
+
+ And the meta_type is registered correctly::
+
+ >>> for info in Products.meta_types:
+ ... if info['name'] == 'Bar Type':
+ ... break
+ >>> info['product']
+ 'Five'
+ >>> info['permission']
+ 'Add Bar'
+ >>> ISimpleContent in info['interfaces']
+ True
+ >>> IPersistent in info['interfaces']
+ True
+ >>> info['visibility']
+ 'Global'
+ >>> info['instance'] is SimpleContent
+ True
+ >>> info['action']
+ ''
+ >>> info['container_filter'] is None
+ True
+
+ Clean up:
+
+ >>> tearDown()
+ >>> SimpleContent.meta_type
+ 'simple item'
+ >>> SimpleContent.icon
+ ''
+ >>> [info for info in Products.meta_types if info['name'] == 'Bar Type']
+ []
+ """
+
+def test_suite():
+ from Testing.ZopeTestCase import ZopeDocTestSuite
+ return ZopeDocTestSuite()
+
+if __name__ == '__main__':
+ framework()
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_registerclass.py
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_security.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_security.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_security.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -45,7 +45,7 @@
Zope 2 can be replaced by ZCML statements without any loss of
information.
- >>> from zope.app.tests.placelesssetup import setUp, tearDown
+ >>> from zope.app.testing.placelesssetup import setUp, tearDown
>>> setUp()
We start out with two classes, ``Dummy1`` and ``Dummy2``. They
@@ -141,7 +141,7 @@
"""
Test checkPermission
- >>> from zope.app.tests.placelesssetup import setUp, tearDown
+ >>> from zope.app.testing.placelesssetup import setUp, tearDown
>>> setUp()
Zope 3 has a function zope.security.checkPermission which provides
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_size.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_size.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_size.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -54,21 +54,21 @@
Set up:
- >>> from zope.app.tests.placelesssetup import setUp, tearDown
+ >>> from zope.app.testing.placelesssetup import setUp, tearDown
>>> setUp()
>>> configure_zcml = '''
... <configure xmlns="http://namespaces.zope.org/zope"
... xmlns:five="http://namespaces.zope.org/five">
- ... <five:sizable class="Products.Five.testing.simplecontent.SimpleContent" />
- ... <five:sizable class="Products.Five.testing.fancycontent.FancyContent" />
+ ... <five:sizable class="Products.Five.tests.testing.simplecontent.SimpleContent" />
+ ... <five:sizable class="Products.Five.tests.testing.fancycontent.FancyContent" />
... <adapter
- ... for="Products.Five.testing.simplecontent.ISimpleContent"
+ ... for="Products.Five.tests.testing.simplecontent.ISimpleContent"
... provides="zope.app.size.interfaces.ISized"
... factory="Products.Five.tests.test_size.SimpleContentSize"
... />
... <adapter
- ... for="Products.Five.testing.fancycontent.IFancyContent"
+ ... for="Products.Five.tests.testing.fancycontent.IFancyContent"
... provides="zope.app.size.interfaces.ISized"
... factory="Products.Five.tests.test_size.FancyContentSize"
... />
@@ -79,8 +79,8 @@
>>> zcml.load_config('meta.zcml', Products.Five)
>>> zcml.load_string(configure_zcml)
- >>> from Products.Five.testing.simplecontent import manage_addSimpleContent
- >>> from Products.Five.testing.fancycontent import manage_addFancyContent
+ >>> from Products.Five.tests.testing.simplecontent import manage_addSimpleContent
+ >>> from Products.Five.tests.testing.fancycontent import manage_addFancyContent
We have registered an ``ISized`` adapter for SimpleContent:
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_viewable.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_viewable.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/test_viewable.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -23,9 +23,6 @@
"""
Testing default view functionality
- >>> from zope.app.tests.placelesssetup import setUp, tearDown
- >>> setUp()
-
Take a class Foo and an interface IFoo:
>>> class Foo:
@@ -37,14 +34,14 @@
Set up a default view for IFoo:
- >>> from zope.app import zapi
- >>> pres = zapi.getGlobalService('Presentation')
+ >>> from zope.component import provideAdapter
+ >>> from zope.component.interfaces import IDefaultViewName
>>> from zope.publisher.interfaces.browser import IBrowserRequest
and default view names for everything and IFoo objects in particular:
- >>> pres.setDefaultViewName(None, IBrowserRequest, u'index.html')
- >>> pres.setDefaultViewName(IFoo, IBrowserRequest, u'foo.html')
+ >>> provideAdapter(u'index.html', (None, IBrowserRequest), IDefaultViewName)
+ >>> provideAdapter(u'foo.html', (IFoo, IBrowserRequest), IDefaultViewName)
Now take a BrowserDefault for an instance of Foo::
@@ -73,10 +70,10 @@
>>> path
[u'foo.html']
+ Clean up adapter registry:
- Clean up:
-
- >>> tearDown()
+ >>> from zope.testing.cleanup import cleanUp
+ >>> cleanUp()
"""
def test_suite():
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/__init__.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/__init__.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/__init__.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,23 @@
+##############################################################################
+#
+# Copyright (c) 2004, 2005 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.
+#
+##############################################################################
+"""Test helpers
+
+$Id$
+"""
+from Products.Five.tests.testing.restricted import RestrictedPythonTestCase
+
+from Products.Five.tests.testing.folder import FiveTraversableFolder
+from Products.Five.tests.testing.folder import manage_addFiveTraversableFolder
+from Products.Five.tests.testing.folder import NoVerifyPasteFolder
+from Products.Five.tests.testing.folder import manage_addNoVerifyPasteFolder
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/fancycontent.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/fancycontent.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/fancycontent.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,65 @@
+##############################################################################
+#
+# Copyright (c) 2004, 2005 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.
+#
+##############################################################################
+"""Test content objects.
+
+$Id$
+"""
+import Acquisition
+from AccessControl import ClassSecurityInfo
+from OFS.SimpleItem import SimpleItem
+from Globals import InitializeClass
+
+from zope.interface import Interface, implements
+
+class IFancyContent(Interface):
+ pass
+
+class FancyAttribute(Acquisition.Explicit):
+ """Doc test fanatics"""
+
+ def __init__(self, name):
+ self.name = name
+
+ security = ClassSecurityInfo()
+
+ security.declarePublic('index_html')
+ def index_html(self, REQUEST):
+ """Doc test fanatics"""
+ return self.name
+
+InitializeClass(FancyAttribute)
+
+class FancyContent(SimpleItem):
+ """A class that already comes with its own __bobo_traverse__ handler.
+ Quite fancy indeed.
+
+ It also comes with its own get_size method.
+ """
+ implements(IFancyContent)
+
+ meta_type = "Fancy Content"
+ security = ClassSecurityInfo()
+
+ def __bobo_traverse__(self, REQUEST, name):
+ return FancyAttribute(name).__of__(self)
+
+ def get_size(self):
+ return 43
+
+InitializeClass(FancyContent)
+
+def manage_addFancyContent(self, id, REQUEST=None):
+ """Add the fancy fancy content."""
+ id = self._setObject(id, FancyContent(id))
+ return ''
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/fancycontent.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/folder.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/folder.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/folder.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,45 @@
+##############################################################################
+#
+# Copyright (c) 2004, 2005 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.
+#
+##############################################################################
+"""Test folders
+
+$Id$
+"""
+from OFS.Folder import Folder
+from OFS.interfaces import IFolder
+from zope.interface import implements
+from Products.Five.traversable import Traversable
+
+class NoVerifyPasteFolder(Folder):
+ """Folder that does not perform paste verification.
+ Used by test_events
+ """
+ def _verifyObjectPaste(self, object, validate_src=1):
+ pass
+
+def manage_addNoVerifyPasteFolder(container, id, title=''):
+ container._setObject(id, NoVerifyPasteFolder())
+ folder = container[id]
+ folder.id = id
+ folder.title = title
+
+class FiveTraversableFolder(Traversable, Folder):
+ """Folder that is five-traversable
+ """
+ implements(IFolder)
+
+def manage_addFiveTraversableFolder(container, id, title=''):
+ container._setObject(id, FiveTraversableFolder())
+ folder = container[id]
+ folder.id = id
+ folder.title = title
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/folder.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/restricted.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/restricted.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/restricted.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,65 @@
+##############################################################################
+#
+# Copyright (c) 2004, 2005 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.
+#
+##############################################################################
+"""Restricted python test helpers
+
+Based on Plone's RestrictedPythonTestCase, with kind permission by the
+Plone developers.
+
+$Id$
+"""
+from AccessControl import Unauthorized
+from Testing.ZopeTestCase import ZopeTestCase
+
+def addPythonScript(folder, id, params='', body=''):
+ """Add a PythonScript to folder."""
+ # clean up any 'ps' that's already here..
+ try:
+ folder._getOb(id)
+ folder.manage_delObjects([id])
+ except AttributeError:
+ pass # it's okay, no 'ps' exists yet
+ factory = folder.manage_addProduct['PythonScripts']
+ factory.manage_addPythonScript(id)
+ folder[id].ZPythonScript_edit(params, body)
+
+def checkRestricted(folder, psbody):
+ """Perform a check by running restricted Python code."""
+ addPythonScript(folder, 'ps', body=psbody)
+ try:
+ folder.ps()
+ except Unauthorized, e:
+ raise AssertionError, e
+
+def checkUnauthorized(folder, psbody):
+ """Perform a check by running restricted Python code. Expect to
+ encounter an Unauthorized exception."""
+ addPythonScript(folder, 'ps', body=psbody)
+ try:
+ folder.ps()
+ except Unauthorized:
+ pass
+ else:
+ raise AssertionError, "Authorized but shouldn't be"
+
+class RestrictedPythonTestCase(ZopeTestCase):
+ """Javiotic test case for restricted code."""
+
+ def addPS(self, id, params='', body=''):
+ addPythonScript(self.folder, id, params, body)
+
+ def check(self, psbody):
+ checkRestricted(self.folder, psbody)
+
+ def checkUnauthorized(self, psbody):
+ checkUnauthorized(self.folder, psbody)
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/restricted.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/simplecontent.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/simplecontent.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/simplecontent.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,90 @@
+##############################################################################
+#
+# Copyright (c) 2004, 2005 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.
+#
+##############################################################################
+"""Simple content class(es) for browser tests
+
+$Id$
+"""
+from OFS.SimpleItem import SimpleItem
+from Globals import InitializeClass
+from AccessControl import ClassSecurityInfo
+
+from zope.interface import Interface, implements
+from Products.Five.traversable import Traversable
+
+class ISimpleContent(Interface):
+ pass
+
+class ICallableSimpleContent(ISimpleContent):
+ pass
+
+class IIndexSimpleContent(ISimpleContent):
+ pass
+
+class SimpleContent(Traversable, SimpleItem):
+ implements(ISimpleContent)
+
+ meta_type = 'Five SimpleContent'
+ security = ClassSecurityInfo()
+
+ def __init__(self, id, title):
+ self.id = id
+ self.title = title
+
+ security.declarePublic('mymethod')
+ def mymethod(self):
+ return "Hello world"
+
+ security.declarePublic('direct')
+ def direct(self):
+ """Should be able to traverse directly to this as there is no view.
+ """
+ return "Direct traversal worked"
+
+InitializeClass(SimpleContent)
+
+class CallableSimpleContent(SimpleItem):
+ """A Viewable piece of content"""
+ implements(ICallableSimpleContent)
+
+ meta_type = "Five CallableSimpleContent"
+
+ def __call__(self, *args, **kw):
+ """ """
+ return "Default __call__ called"
+
+InitializeClass(CallableSimpleContent)
+
+class IndexSimpleContent(SimpleItem):
+ """A Viewable piece of content"""
+ implements(IIndexSimpleContent)
+
+ meta_type = 'Five IndexSimpleContent'
+
+ def index_html(self, *args, **kw):
+ """ """
+ return "Default index_html called"
+
+InitializeClass(IndexSimpleContent)
+
+def manage_addSimpleContent(self, id, title, REQUEST=None):
+ """Add the simple content."""
+ self._setObject(id, SimpleContent(id, title))
+
+def manage_addCallableSimpleContent(self, id, title, REQUEST=None):
+ """Add the viewable simple content."""
+ self._setObject(id, CallableSimpleContent(id, title))
+
+def manage_addIndexSimpleContent(self, id, title, REQUEST=None):
+ """Add the viewable simple content."""
+ self._setObject(id, IndexSimpleContent(id, title))
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/tests/testing/simplecontent.py
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/traversable.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/traversable.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/traversable.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -13,28 +13,29 @@
##############################################################################
"""Machinery for making things traversable through adaptation
-$Id: traversable.py 18841 2005-10-23 09:57:38Z philikon $
+$Id: traversable.py 19283 2005-10-31 17:43:51Z philikon $
"""
from zExceptions import NotFound
-from zope.exceptions import NotFoundError
-from zope.component import getView, ComponentLookupError
-from zope.interface import implements
+
+from zope.component import getMultiAdapter, ComponentLookupError
+from zope.interface import implements, Interface
+from zope.publisher.interfaces import ILayer
from zope.publisher.interfaces.browser import IBrowserRequest
+
from zope.app.traversing.interfaces import ITraverser, ITraversable
from zope.app.traversing.adapters import DefaultTraversable
from zope.app.traversing.adapters import traversePathElement
+from zope.app.publication.browser import setDefaultSkin
+from zope.app.interface import queryType
from AccessControl import getSecurityManager
from Products.Five.security import newInteraction
_marker = object
-class FakeRequest:
+class FakeRequest(dict):
implements(IBrowserRequest)
- def getPresentationSkin(self):
- return None
-
def has_key(self, key):
return False
@@ -69,16 +70,20 @@
REQUEST = getattr(self, 'REQUEST', None)
if not IBrowserRequest.providedBy(REQUEST):
REQUEST = FakeRequest()
+
+ # set the default skin on the request if it doesn't have any
+ # layers set on it yet
+ if queryType(REQUEST, ILayer) is None:
+ setDefaultSkin(REQUEST)
+
# con Zope 3 into using Zope 2's checkPermission
newInteraction()
-
try:
return ITraverser(self).traverse(
path=[name], request=REQUEST).__of__(self)
- except (ComponentLookupError, NotFoundError,
+ except (ComponentLookupError, LookupError,
AttributeError, KeyError, NotFound):
pass
-
try:
return getattr(self, name)
except AttributeError:
@@ -100,8 +105,9 @@
REQUEST = getattr(context, 'REQUEST', None)
if not IBrowserRequest.providedBy(REQUEST):
REQUEST = FakeRequest()
- # Try to lookup a view first
+ setDefaultSkin(REQUEST)
+ # Try to lookup a view
try:
- return getView(context, name, REQUEST)
+ return getMultiAdapter((context, REQUEST), Interface, name)
except ComponentLookupError:
pass
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/__init__.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/__init__.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/__init__.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1 @@
+# make this directory a package
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/__init__.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/__init__.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/__init__.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1 @@
+# make this directory a package
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/configure.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/configure.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/configure.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,20 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+ xmlns:browser="http://namespaces.zope.org/browser">
+
+ <browser:page
+ for="*"
+ name="edit-markers.html"
+ template="edit_markers.pt"
+ class="Products.Five.utilities.browser.marker.EditView"
+ permission="zope2.ManageProperties"
+ />
+
+ <browser:page
+ for="*"
+ name="manage_interfaces"
+ template="manage_interfaces.pt"
+ class="Products.Five.utilities.browser.marker.EditView"
+ permission="zope2.ManageProperties"
+ />
+
+</configure>
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/configure.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/edit_markers.pt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/edit_markers.pt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/edit_markers.pt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,63 @@
+<html metal:use-macro="context/@@standard_macros/page">
+<body>
+
+<metal:slot metal:fill-slot="body">
+<metal:macro metal:define-macro="heading">
+<h1 i18n:translate="heading_edit_marker">Assign Marker Interfaces</h1>
+</metal:macro>
+<metal:macro metal:define-macro="main">
+<p class="form-help formHelp" i18n:translate="">Change the behavior of this
+ object by adding or removing marker interfaces. You can choose one or more
+ interfaces to be added to the list of provided interfaces for this
+ object.</p>
+
+<p class="form-help formHelp" i18n:translate="">A marker interface is used to
+ identify an instance of a piece of content. When in conjunction with Five,
+ this allows you to enable and disable views based on marker interfaces for
+ example.</p>
+
+<form action="." method="post"
+ tal:attributes="action request/ACTUAL_URL">
+
+<fieldset>
+ <legend i18n:translate="legend_provided">Provided Interfaces</legend>
+ <tal:loop tal:repeat="interface view/getInterfaceNames">
+
+ <label class="form-mono"
+ tal:content="interface/name" i18n:translate="">INTERFACE</label><br />
+ </tal:loop>
+ <tal:loop tal:repeat="interface view/getDirectlyProvidedNames">
+ <input type="checkbox" id="INTERFACE" name="remove:list"
+ tal:attributes="id interface/name; value interface/name" />
+ <label class="form-mono" for="INTERFACE" tal:attributes="for interface/name"
+ tal:content="interface/name" i18n:translate="">INTERFACE</label><br />
+ </tal:loop>
+ <tal:case tal:condition="view/getDirectlyProvidedNames">
+ <div class="formControls FormButtons">
+ <input class="form-element" type="submit" name="SAVE" value="Remove"
+ i18n:attributes="value" />
+ </div>
+ </tal:case>
+</fieldset>
+
+<fieldset>
+ <legend i18n:translate="legend_available_marker">Available Marker
+ Interfaces</legend>
+ <tal:loop tal:repeat="interface view/getAvailableInterfaceNames">
+ <input type="checkbox" id="INTERFACE" name="add:list"
+ tal:attributes="id interface/name; value interface/name" />
+ <label class="form-mono" for="INTERFACE" tal:attributes="for interface/name"
+ tal:content="interface/name" i18n:translate="">INTERFACE</label><br />
+ </tal:loop>
+ <div class="formControls FormButtons">
+ <input class="form-element" type="submit" name="SAVE" value="Add"
+ i18n:attributes="value" />
+ </div>
+</fieldset>
+
+</form>
+</metal:macro>
+</metal:slot>
+
+</body>
+</html>
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/edit_markers.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/manage_interfaces.pt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/manage_interfaces.pt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/manage_interfaces.pt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,7 @@
+<h1 tal:replace="structure context/manage_page_header">PAGE HEADER</h1>
+<h2 tal:replace="structure context/manage_tabs">TABS</h2>
+<style type="text/css">
+ fieldset {width:auto; float:left}
+</style>
+<metal:macro metal:use-macro="context/@@edit-markers.html/main" />
+<h1 tal:replace="structure context/manage_page_footer">PAGE FOOTER</h1>
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/manage_interfaces.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/marker.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/marker.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/marker.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,62 @@
+##############################################################################
+#
+# Copyright (c) 2004, 2005 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.
+#
+##############################################################################
+"""Marker interfaces adapter views.
+
+$Id$
+"""
+from Products.Five.utilities.interfaces import IMarkerInterfaces
+
+
+class EditView:
+
+ """Marker interface edit view.
+ """
+
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+ self.adapted = IMarkerInterfaces(context)
+ self.context_url = self.context.absolute_url()
+
+ def __call__(self, SAVE=None, add=(), remove=()):
+ if SAVE:
+ self.update(add, remove)
+ self.request.response.redirect(self.request.ACTUAL_URL)
+ return ''
+ return self.index()
+
+ def _getLinkToInterfaceDetailsView(self, interfaceName):
+ return (self.context_url +
+ '/views-details.html?iface=%s&type=zope.publisher.interfaces.browser.IBrowserRequest' % interfaceName)
+
+ def _getNameLinkDicts(self, interfaceNames):
+ return [dict(name=name,
+ link=self._getLinkToInterfaceDetailsView(name))
+ for name in interfaceNames]
+
+ def getAvailableInterfaceNames(self):
+ return self._getNameLinkDicts(
+ self.adapted.getAvailableInterfaceNames())
+
+ def getDirectlyProvidedNames(self):
+ return self._getNameLinkDicts(self.adapted.getDirectlyProvidedNames())
+
+ def getInterfaceNames(self):
+ return self._getNameLinkDicts(self.adapted.getInterfaceNames())
+
+ def update(self, add, remove):
+ # this could return errors
+ add = self.adapted.dottedToInterfaces(add)
+ remove = self.adapted.dottedToInterfaces(remove)
+ self.adapted.update(add=add, remove=remove)
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/marker.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/tests/__init__.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/tests/__init__.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/tests/__init__.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1 @@
+# make this directory a package
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/tests/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/tests/framework.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/tests/framework.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/tests/framework.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,107 @@
+##############################################################################
+#
+# ZopeTestCase
+#
+# COPY THIS FILE TO YOUR 'tests' DIRECTORY.
+#
+# This version of framework.py will use the SOFTWARE_HOME
+# environment variable to locate Zope and the Testing package.
+#
+# If the tests are run in an INSTANCE_HOME installation of Zope,
+# Products.__path__ and sys.path with be adjusted to include the
+# instance's Products and lib/python directories respectively.
+#
+# If you explicitly set INSTANCE_HOME prior to running the tests,
+# auto-detection is disabled and the specified path will be used
+# instead.
+#
+# If the 'tests' directory contains a custom_zodb.py file, INSTANCE_HOME
+# will be adjusted to use it.
+#
+# If you set the ZEO_INSTANCE_HOME environment variable a ZEO setup
+# is assumed, and you can attach to a running ZEO server (via the
+# instance's custom_zodb.py).
+#
+##############################################################################
+#
+# The following code should be at the top of every test module:
+#
+# import os, sys
+# if __name__ == '__main__':
+# execfile(os.path.join(sys.path[0], 'framework.py'))
+#
+# ...and the following at the bottom:
+#
+# if __name__ == '__main__':
+# framework()
+#
+##############################################################################
+
+__version__ = '0.2.3'
+
+# Save start state
+#
+__SOFTWARE_HOME = os.environ.get('SOFTWARE_HOME', '')
+__INSTANCE_HOME = os.environ.get('INSTANCE_HOME', '')
+
+if __SOFTWARE_HOME.endswith(os.sep):
+ __SOFTWARE_HOME = os.path.dirname(__SOFTWARE_HOME)
+
+if __INSTANCE_HOME.endswith(os.sep):
+ __INSTANCE_HOME = os.path.dirname(__INSTANCE_HOME)
+
+# Find and import the Testing package
+#
+if not sys.modules.has_key('Testing'):
+ p0 = sys.path[0]
+ if p0 and __name__ == '__main__':
+ os.chdir(p0)
+ p0 = ''
+ s = __SOFTWARE_HOME
+ p = d = s and s or os.getcwd()
+ while d:
+ if os.path.isdir(os.path.join(p, 'Testing')):
+ zope_home = os.path.dirname(os.path.dirname(p))
+ sys.path[:1] = [p0, p, zope_home]
+ break
+ p, d = s and ('','') or os.path.split(p)
+ else:
+ print 'Unable to locate Testing package.',
+ print 'You might need to set SOFTWARE_HOME.'
+ sys.exit(1)
+
+import Testing, unittest
+execfile(os.path.join(os.path.dirname(Testing.__file__), 'common.py'))
+
+# Include ZopeTestCase support
+#
+if 1: # Create a new scope
+
+ p = os.path.join(os.path.dirname(Testing.__file__), 'ZopeTestCase')
+
+ if not os.path.isdir(p):
+ print 'Unable to locate ZopeTestCase package.',
+ print 'You might need to install ZopeTestCase.'
+ sys.exit(1)
+
+ ztc_common = 'ztc_common.py'
+ ztc_common_global = os.path.join(p, ztc_common)
+
+ f = 0
+ if os.path.exists(ztc_common_global):
+ execfile(ztc_common_global)
+ f = 1
+ if os.path.exists(ztc_common):
+ execfile(ztc_common)
+ f = 1
+
+ if not f:
+ print 'Unable to locate %s.' % ztc_common
+ sys.exit(1)
+
+# Debug
+#
+print 'SOFTWARE_HOME: %s' % os.environ.get('SOFTWARE_HOME', 'Not set')
+print 'INSTANCE_HOME: %s' % os.environ.get('INSTANCE_HOME', 'Not set')
+sys.stdout.flush()
+
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/tests/framework.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/tests/test_marker.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/tests/test_marker.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/tests/test_marker.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,96 @@
+##############################################################################
+#
+# Copyright (c) 2004, 2005 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.
+#
+##############################################################################
+"""Unit tests for marker interface views.
+
+$Id$
+"""
+import os, sys
+if __name__ == '__main__':
+ execfile(os.path.join(sys.path[0], 'framework.py'))
+
+def test_editview():
+ """
+ Set everything up:
+
+ >>> from zope.app.testing.placelesssetup import setUp, tearDown
+ >>> setUp()
+ >>> import Products.Five
+ >>> import Products.Five.utilities
+ >>> from Products.Five import zcml
+ >>> zcml.load_config('meta.zcml', Products.Five)
+ >>> zcml.load_config('permissions.zcml', Products.Five)
+ >>> zcml.load_config('configure.zcml', Products.Five.utilities)
+ >>> from Products.Five.utilities.browser.marker import EditView
+ >>> from Products.Five.tests.testing.simplecontent import SimpleContent
+ >>> obj = SimpleContent('foo', 'Foo').__of__(self.folder)
+
+ Create an EditView:
+
+ >>> view = EditView(obj, {})
+ >>> view.context.aq_inner is obj
+ True
+ >>> view.request
+ {}
+ >>> view.getAvailableInterfaceNames()
+ []
+ >>> view.getDirectlyProvidedNames()
+ []
+ >>> view.getInterfaceNames()
+ [...ISimpleContent...]
+
+ Try to add a marker interface that doesn't exist:
+
+ >>> view.update(('__builtin__.IFooMarker',), ())
+ Traceback (most recent call last):
+ ...
+ ComponentLookupError...
+
+ Now create the marker interface:
+
+ >>> from Products.Five.tests.testing.simplecontent import ISimpleContent
+ >>> class IFooMarker(ISimpleContent): pass
+ >>> from zope.app.component.interface import provideInterface
+ >>> provideInterface('', IFooMarker)
+ >>> view.getAvailableInterfaceNames()
+ [...IFooMarker...]
+ >>> view.getDirectlyProvidedNames()
+ []
+
+ And try again to add it to the object:
+
+ >>> view.update(('__builtin__.IFooMarker',), ())
+ >>> view.getAvailableInterfaceNames()
+ []
+ >>> view.getDirectlyProvidedNames()
+ [...IFooMarker...]
+
+ And remove it again:
+
+ >>> view.update((), ('__builtin__.IFooMarker',))
+ >>> view.getAvailableInterfaceNames()
+ [...IFooMarker...]
+ >>> view.getDirectlyProvidedNames()
+ []
+
+ Finally tear down:
+
+ >>> tearDown()
+ """
+
+def test_suite():
+ from Testing.ZopeTestCase import ZopeDocTestSuite
+ return ZopeDocTestSuite()
+
+if __name__ == '__main__':
+ framework()
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/browser/tests/test_marker.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/configure.zcml
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/configure.zcml 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/configure.zcml 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,12 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+
+ <include package=".browser"/>
+
+ <adapter
+ for="*"
+ provides=".interfaces.IMarkerInterfaces"
+ factory=".marker.MarkerInterfacesAdapter"
+ permission="zope2.ManageProperties"
+ />
+
+</configure>
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/configure.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/interfaces.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/interfaces.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/interfaces.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,74 @@
+##############################################################################
+#
+# Copyright (c) 2004, 2005 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.
+#
+##############################################################################
+"""Utility Interface Definitions.
+
+$Id$
+"""
+from zope.interface import Interface
+
+
+class IReadInterface(Interface):
+
+ def getDirectlyProvided():
+ """List the interfaces directly implemented by the object.
+ """
+
+ def getDirectlyProvidedNames():
+ """List the names of interfaces directly implemented by the object.
+ """
+
+ def getAvailableInterfaces():
+ """List the marker interfaces available for the object.
+ """
+
+ def getAvailableInterfaceNames():
+ """List the names of marker interfaces available for the object.
+ """
+
+ def getInterfaces():
+ """List interfaces provided by the class of the object.
+ """
+
+ def getInterfaceNames():
+ """List the names of interfaces provided by the class of the object.
+ """
+
+ def getProvided():
+ """List interfaces provided by the object.
+ """
+
+ def getDirectlyProvidedNames():
+ """List the names of interfaces provided by the object.
+ """
+
+
+class IWriteInterface(Interface):
+
+ def update(add=(), remove=()):
+ """Update directly provided interfaces of the object.
+ """
+
+ def mark(interface):
+ """Add interface to interfaces the object directly provides.
+ """
+
+ def erase(interface):
+ """Remove interfaces from interfaces the object directly provides.
+ """
+
+
+class IMarkerInterfaces(IReadInterface, IWriteInterface):
+
+ """Provides methods for inspecting and assigning marker interfaces.
+ """
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/interfaces.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/marker.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/marker.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/marker.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -0,0 +1,133 @@
+##############################################################################
+#
+# Copyright (c) 2004, 2005 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.
+#
+##############################################################################
+"""Marker interfaces adapter.
+
+Allows for arbitrary application of marker interfaces to objects.
+
+$Id$
+"""
+from sets import Set
+
+from zope.interface import implements
+from zope.interface import implementedBy
+from zope.interface import directlyProvidedBy
+from zope.interface import directlyProvides
+from zope.interface import providedBy
+from zope.interface.interfaces import IInterface
+from zope.app.component.interface import getInterface, interfaceToName
+from zope.app.component.interface import searchInterface
+
+from interfaces import IMarkerInterfaces
+
+def interfaceStringCheck(f):
+ def wrapper(ob, interface):
+ if isinstance(interface, str):
+ interface = getInterface(ob, interface)
+ return f(ob, interface)
+ return wrapper
+
+def mark(ob, interface):
+ directlyProvides(ob, directlyProvidedBy(ob), interface)
+
+def erase(ob, interface):
+ directlyProvides(ob, directlyProvidedBy(ob)-interface)
+
+mark = interfaceStringCheck(mark)
+erase = interfaceStringCheck(erase)
+
+
+class MarkerInterfacesAdapter(object):
+
+ implements(IMarkerInterfaces)
+
+ mark = staticmethod(mark)
+ erase = staticmethod(erase)
+
+ def __init__(self, context):
+ self.context = context
+
+ def dottedToInterfaces(self, seq):
+ return [getInterface(self.context, dotted) for dotted in seq]
+
+ def getDirectlyProvided(self):
+ return directlyProvidedBy(self.context)
+
+ def getDirectlyProvidedNames(self):
+ return self._getInterfaceNames(self.getDirectlyProvided())
+
+ def getAvailableInterfaces(self):
+ results = []
+ todo = list(providedBy(self.context))
+ done = []
+ while todo:
+ interface = todo.pop()
+ done.append(interface)
+ for base in interface.__bases__:
+ if base not in todo and base not in done:
+ todo.append(base)
+ markers = self._getDirectMarkersOf(interface)
+ for interface in markers:
+ if (interface not in results
+ and not interface.providedBy(self.context)):
+ results.append(interface)
+ todo += markers
+ return tuple(results)
+
+ def getAvailableInterfaceNames(self):
+ names = self._getInterfaceNames(self.getAvailableInterfaces())
+ names.sort()
+ return names
+
+ def getInterfaces(self):
+ return tuple(implementedBy(self.context.__class__))
+
+ def getInterfaceNames(self):
+ return self._getInterfaceNames(self.getInterfaces())
+
+ def getProvided(self):
+ return providedBy(self.context)
+
+ def getProvidedNames(self):
+ return self._getInterfaceNames(self.getProvided())
+
+ def update(self, add=(), remove=()):
+ """Currently update adds and then removes, rendering duplicate null.
+ """
+ marker_ifaces = self.getAvailableInterfaces()
+ if len(add):
+ [mark(self.context, interface)
+ for interface in Set(marker_ifaces) & Set(add)]
+
+ direct_ifaces = self.getDirectlyProvided()
+ if len(remove):
+ [erase(self.context, interface)
+ for interface in Set(direct_ifaces) & Set(remove)]
+
+ def _getInterfaceNames(self, interfaces):
+ return [interfaceToName(self, iface) for iface in interfaces]
+
+ def _getDirectMarkersOf(self, base):
+ """Get empty interfaces directly inheriting from the given one.
+ """
+ results = []
+ interfaces = searchInterface(None, base=base)
+ for interface in interfaces:
+ # There are things registered with the interface service
+ # that are not interfaces. Yay!
+ if not IInterface.providedBy(interface):
+ continue
+ if base in interface.__bases__ and not interface.names():
+ results.append(interface)
+ results.sort()
+ return tuple(results)
Property changes on: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/utilities/marker.py
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/version.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/version.txt 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/version.txt 2005-11-02 17:17:42 UTC (rev 39847)
@@ -1 +1 @@
-Five 1.1
+Five 1.3b
Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/Five/viewable.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/Five/viewable.py 2005-11-02 14:51:27 UTC (rev 39846)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/Five/viewable.py 2005-11-02 17:17:42 UTC (rev 39847)
@@ -17,10 +17,10 @@
"""
import inspect
from zExceptions import NotFound
-from zope.exceptions import NotFoundError
-from zope.component import getView, getDefaultViewName, ComponentLookupError
+from zope.component import ComponentLookupError
from zope.interface import implements
from zope.publisher.interfaces.browser import IBrowserRequest
+from zope.app.zapi import getDefaultViewName
from Products.Five.traversable import FakeRequest
from Products.Five.interfaces import IBrowserDefault
More information about the Zope-Checkins
mailing list