[z3-checkins] r5635 - in z3/Five/trunk: . doc tests
tests/products/FiveTest
philikon at codespeak.net
philikon at codespeak.net
Fri Jul 23 16:05:02 MEST 2004
Author: philikon
Date: Fri Jul 23 16:05:01 2004
New Revision: 5635
Added:
z3/Five/trunk/tests/products/FiveTest/fancycontent.py
Modified:
z3/Five/trunk/doc/TODO.txt
z3/Five/trunk/fiveconfigure.py
z3/Five/trunk/tests/products/FiveTest/__init__.py
z3/Five/trunk/tests/products/FiveTest/browser.py
z3/Five/trunk/tests/products/FiveTest/configure.zcml
z3/Five/trunk/tests/products/FiveTest/interfaces.py
z3/Five/trunk/tests/test_five.py
z3/Five/trunk/viewable.py
Log:
Kill off two TODO items before the 0.1 release:
- Make five:viewable allow being called several times. Once it
is called for a class, or if the class inherits from Viewable
directly, a marker, __five_viewable__ is put on the class
which tells five:viewable to simply ignore the request.
- Support the coexisting with already existing __bobo_traverse__
methods. If five:viewable finds a class with such a method,
it renames the method to __fallback_traverse__ and overwrites
it with Viewable's __bobo_traverse__. That way, Zope3-style
views receive precedence over custom class view wirings.
The default __fallback_traverse__ raises NotFound.
Modified: z3/Five/trunk/doc/TODO.txt
==============================================================================
--- z3/Five/trunk/doc/TODO.txt (original)
+++ z3/Five/trunk/doc/TODO.txt Fri Jul 23 16:05:01 2004
@@ -2,8 +2,6 @@
TODO
====
-- make five:viewable support being called several times
-
- allow Zope2 boilerplate context.registerClass be configured thru zcml
- implement/register missing zope.app directives:
@@ -12,8 +10,6 @@
* ...
-- support existing __bobo_traverse__ methods
-
- secure page templates
- now that we have zope:content, do we still need five:implements?
Modified: z3/Five/trunk/fiveconfigure.py
==============================================================================
--- z3/Five/trunk/fiveconfigure.py (original)
+++ z3/Five/trunk/fiveconfigure.py Fri Jul 23 16:05:01 2004
@@ -65,9 +65,21 @@
)
def classViewable(class_):
+ # if a class already has this attribute, it means it is either a
+ # subclass of api.Viewable or was already processed with this
+ # directive; in either case, do nothing...
+ if hasattr(class_, '__five_viewable__'):
+ return
+
if hasattr(class_, '__bobo_traverse__'):
- raise TypeError("__bobo_traverse already__ exists on %s" % class_)
+ # if there's an existing bobo_traverse hook already, use that
+ # as the traversal fallback method
+ setattr(class_, "__fallback_traverse__", class_.__bobo_traverse__)
+ else:
+ setattr(class_, "__fallback_traverse__", Viewable.__fallback_traverse__)
+
setattr(class_, '__bobo_traverse__', Viewable.__bobo_traverse__)
+ setattr(class_, '__five_viewable__', True)
def viewable(_context, class_):
_context.action(
Modified: z3/Five/trunk/tests/products/FiveTest/__init__.py
==============================================================================
--- z3/Five/trunk/tests/products/FiveTest/__init__.py (original)
+++ z3/Five/trunk/tests/products/FiveTest/__init__.py Fri Jul 23 16:05:01 2004
@@ -1,5 +1,6 @@
import Products
import simplecontent
+import fancycontent
def initialize(context):
@@ -8,3 +9,8 @@
constructors = (simplecontent.manage_addSimpleContentForm,
simplecontent.manage_addSimpleContent),
)
+
+ context.registerClass(
+ fancycontent.FancyContent,
+ constructors = (fancycontent.manage_addFancyContent,)
+ )
Modified: z3/Five/trunk/tests/products/FiveTest/browser.py
==============================================================================
--- z3/Five/trunk/tests/products/FiveTest/browser.py (original)
+++ z3/Five/trunk/tests/products/FiveTest/browser.py Fri Jul 23 16:05:01 2004
@@ -11,6 +11,12 @@
"""Docstring"""
return "The mouse has been eaten by the eagle"
+class FancyContentView(BrowserView):
+ """Fancy, fancy stuff"""
+
+ def view(self):
+ return "Fancy, fancy"
+
class CallableNoDocstring:
def __call__(self):
Modified: z3/Five/trunk/tests/products/FiveTest/configure.zcml
==============================================================================
--- z3/Five/trunk/tests/products/FiveTest/configure.zcml (original)
+++ z3/Five/trunk/tests/products/FiveTest/configure.zcml Fri Jul 23 16:05:01 2004
@@ -2,6 +2,19 @@
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:five="http://namespaces.zope.org/five">
+ <!-- this is a test whether five:viewable can be called more than
+ once on a class; SimpleContent inherits from api.Viewable, so
+ one directive suffices here -->
+
+ <five:viewable class=".simplecontent.SimpleContent" />
+
+
+ <!-- this tests whether five:viewable can be called on a class that
+ already provides __bobo_traverse__, such as our FancyContent -->
+
+ <five:viewable class=".fancycontent.FancyContent" />
+
+
<adapter
for=".interfaces.IAdaptable"
provides=".interfaces.IAdapted"
@@ -17,6 +30,14 @@
permission="zope2.ViewManagementScreens"
/>
+ <browser:page
+ for=".interfaces.IFancyContent"
+ class=".browser.FancyContentView"
+ attribute="view"
+ name="fancy"
+ permission="zope2.Public"
+ />
+
<browser:pages
for=".interfaces.ISimpleContent"
class=".browser.NoDocstringView"
Added: z3/Five/trunk/tests/products/FiveTest/fancycontent.py
==============================================================================
--- (empty file)
+++ z3/Five/trunk/tests/products/FiveTest/fancycontent.py Fri Jul 23 16:05:01 2004
@@ -0,0 +1,40 @@
+import Acquisition
+from AccessControl import ClassSecurityInfo
+from OFS.SimpleItem import SimpleItem
+from Globals import InitializeClass
+
+from zope.interface import implements
+from interfaces import IFancyContent
+
+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."""
+ implements(IFancyContent)
+
+ meta_type = "Fancy Content"
+ security = ClassSecurityInfo()
+
+ def __bobo_traverse__(self, REQUEST, name):
+ return FancyAttribute(name).__of__(self)
+
+InitializeClass(FancyContent)
+
+def manage_addFancyContent(self, id, REQUEST=None):
+ """Add the fancy fancy content."""
+ id = self._setObject(id, FancyContent(id))
+ return ''
Modified: z3/Five/trunk/tests/products/FiveTest/interfaces.py
==============================================================================
--- z3/Five/trunk/tests/products/FiveTest/interfaces.py (original)
+++ z3/Five/trunk/tests/products/FiveTest/interfaces.py Fri Jul 23 16:05:01 2004
@@ -26,3 +26,6 @@
class ISimpleContent(Interface):
pass
+
+class IFancyContent(Interface):
+ pass
Modified: z3/Five/trunk/tests/test_five.py
==============================================================================
--- z3/Five/trunk/tests/test_five.py (original)
+++ z3/Five/trunk/tests/test_five.py Fri Jul 23 16:05:01 2004
@@ -138,6 +138,22 @@
response = self.publish('/test_folder_1_/testoid/%s' % view_name)
self.assertEquals("No docstring", response.getBody())
+ def test_fallback_raises_notfound(self):
+ response = self.publish('/test_folder_1_/testoid/doesntexist')
+ self.assertEquals(404, response.getStatus())
+
+ def test_existing_bobo_traverse(self):
+ self.folder.manage_addProduct['FiveTest'].manage_addFancyContent(
+ 'fancy')
+
+ # check if z3-based view lookup works
+ response = self.publish('/test_folder_1_/fancy/fancy')
+ self.assertEquals("Fancy, fancy", response.getBody())
+
+ # check if the old bobo_traverse method can still kick in
+ response = self.publish('/test_folder_1_/fancy/something-else')
+ self.assertEquals('something-else', response.getBody())
+
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(FiveTestCase))
Modified: z3/Five/trunk/viewable.py
==============================================================================
--- z3/Five/trunk/viewable.py (original)
+++ z3/Five/trunk/viewable.py Fri Jul 23 16:05:01 2004
@@ -27,33 +27,38 @@
class Viewable:
"""A mixin to make an object viewable using the Zope 3 system.
"""
+ __five_viewable__ = True
+
+ def __fallback_traverse__(self, REQUEST, name):
+ """Method hook for fallback traversal
+
+ This method is called by __bobo_traverse___ when Zope3-style
+ view lookup fails. By default, we do what Zope 2 would do,
+ raise a NotFound error."""
+ try:
+ REQUEST.RESPONSE.notFoundError("%s " % name)
+ except AttributeError:
+ raise KeyError, name
+
def __bobo_traverse__(self, REQUEST, name):
+ """Hook for Zope 2 traversal
+
+ This method is called by Zope 2's ZPublisher upon traversal.
+ It allows us to trick it into publishing Zope 3-style views.
+ """
+ if not IBrowserRequest.providedBy(REQUEST):
+ REQUEST = FakeRequest()
+ try:
+ return getView(self, name, REQUEST).__of__(self)
+ except ComponentLookupError:
+ pass
+ try:
+ return getattr(self, name)
+ except AttributeError:
+ pass
try:
- if not IBrowserRequest.providedBy(REQUEST):
- REQUEST = FakeRequest()
- try:
- return getView(self, name, REQUEST).__of__(self)
- except ComponentLookupError:
- pass
- try:
- return getattr(self, name)
- except AttributeError:
- pass
- try:
- return self[name]
- except (AttributeError, KeyError):
- pass
- # XXX not sure this is very useful
- #method = REQUEST.get('REQUEST_METHOD', 'GET')
- #if not method in ('GET', 'POST'):
- # return NullResource(self, name, REQUEST).__of__(self)
+ return self[name]
+ except (AttributeError, KeyError):
+ pass
- # Waaa. See Application.py
- try:
- REQUEST.RESPONSE.notFoundError("%s " % name)
- except AttributeError:
- raise KeyError, name
- except:
- import traceback
- traceback.print_exc()
- raise
+ return self.__fallback_traverse__(REQUEST, name)
More information about the z3-checkins
mailing list