Commit dad37b5e authored by Hanno Schlichting's avatar Hanno Schlichting

flake8'ed Five

parent 0c3ecbb0
Five is distributed under the provisions of the Zope Public License
(ZPL) v2.1. See doc/ZopePublicLicense.txt for the license text.
Copyright (C) 2005 Five Contributors. See CREDITS.txt for a list of
Five contributors.
Five contains source code derived from:
- Zope, copyright (C) 2001-2005 by Zope Corporation.
- TrustedExecutables. Dieter Mauer kindly allow licensing this under the
ZPL 2.1.
Five contributors
-----------------
- Martijn Faassen (faassen@infrae.com)
- Sidnei da Silva (sidnei@awkly.org)
- Philipp von Weitershausen (philikon@philikon.de)
- Lennart Regebro (regebro@nuxeo.com)
- Tres Seaver (tseaver@palladion.com)
- Jan-Wijbrand Kolman (jw@infrae.com)
- Stefan Holek (ssh@epy.co.at)
- Florent Guillaume (fg@nuxeo.com)
- Godefroid Chapelle (gotcha@bubblenet.be)
- Andy Adiwidjaja (mail@adiwidjaja.com)
- Stuart Bishop (stuart@stuartbishop.net)
- Simon Eisenmann (simon@struktur.de)
- Dieter Maurer (dieter@handshake.de)
- Yvo Schubbe (y.2007-@wcm-solutions.de)
- Malcolm Cleaton (malcolm@jamkit.com)
- Tarek Ziad (tziade@nuxeo.com)
- Whit Morriss (whit@longnow.org)
- Brian Sutherland (jinty@web.de)
- Rocky Burt (rocky@serverzen.com)
Thank you
---------
Infrae for the initial development and continuing support.
Martijn Faassen would like to thank ETH Zurich for their support and
encouragement during the initial development of Five.
Nuxeo for significant contributions to making Five usable in the real
world.
Dieter Maurer for use of code from TrustedExecutables within Five
under the ZPL.
The Five developers would like to thank the Zope developers, in
particular Jim Fulton, for the mountain to stand on.
Introduction
------------
"It was the dawn of the third age of Zope. The Five project was a dream
given form. Its goal: to use Zope 3 technologies in Zope 2.7 by
creating a Zope 2 product where Zope 3 and Zope 2 could work out their
differences peacefully." -- Babylon 5, creatively quoted
"The Law of Fives states simply that: ALL THINGS HAPPEN IN FIVES, OR
ARE DIVISIBLE BY OR ARE MULTIPLES OF FIVE, OR ARE SOMEHOW DIRECTLY OR
INDIRECTLY RELATED TO FIVE.
THE LAW OF FIVES IS NEVER WRONG." -- Principia Discordia
What is Five?
-------------
A couple of years back an attempt was made to rewrite Zope 2 from scratch and
provide an upgrade path from current Zope 2 to the new version. This project
used the name Zope 3. The attempt of writing a newer version of a full blown
application server similar to Zope 2 failed. Instead the project generated a
whole lot of underlying technologies and new concepts packaged up in reusable
libraries.
Five is the project that integrates those technologies and packages into
Zope 2. It's name is a pun on the original naming of Zope 2 + Zope 3 = Zope 5.
Among others, it allows you to use zope.interface, ZCML-based configuration,
adapters, browser pages (including layers, and resources), zope.schemas,
object events, as well as zope.i18n message catalogs.
We've tried to keep the Five experience as close to that of the integrated
Zope packages as possible, so this means that what you learn while using Five
should also be applicable to the Zope packages directly.
====
TODO
====
- container events - get rid of deprecation warnings
- make rendering of resource urls support sites?
- HTTP/WebDAV: support dispatching of all HTTP/WebDAV methods to HTTP
views. If lookup fails, fall back to methods on the object (Zope 2
style). Security is implied by HTTP views.
- FTP: allow manage_FTPstat, manage_FTPget, manage_FTPlist to dispatch to
filerepresentation adapters. Make sure to handle security correctly.
- Grant security stuff through ZCML (<grant />)?
- top-level <require />, <allow /> directives as a ZCML spelling of
allowModule, allowClass
...@@ -14,16 +14,14 @@ ...@@ -14,16 +14,14 @@
"""Initialize the Five product """Initialize the Five product
""" """
# public API provided by Five from Products.Five.browser import BrowserView # NOQA
# usage: from Products.Five import <something> from Products.Five.skin.standardmacros import StandardMacros # NOQA
from Products.Five.browser import BrowserView
from Products.Five.skin.standardmacros import StandardMacros
# some convenience methods/decorators
def fivemethod(func): def fivemethod(func):
func.__five_method__ = True func.__five_method__ = True
return func return func
def isFiveMethod(m): def isFiveMethod(m):
return hasattr(m, '__five_method__') return hasattr(m, '__five_method__')
...@@ -19,7 +19,7 @@ factory screen. ...@@ -19,7 +19,7 @@ factory screen.
(original: zope.app.container.browser.adding) (original: zope.app.container.browser.adding)
""" """
__docformat__ = 'restructuredtext' import operator
from zope.browser.interfaces import IAdding from zope.browser.interfaces import IAdding
from zope.browsermenu.menu import getMenu from zope.browsermenu.menu import getMenu
...@@ -30,7 +30,7 @@ from zope.component import queryUtility ...@@ -30,7 +30,7 @@ from zope.component import queryUtility
from zope.component.interfaces import IFactory from zope.component.interfaces import IFactory
from zope.container.constraints import checkFactory from zope.container.constraints import checkFactory
from zope.container.constraints import checkObject from zope.container.constraints import checkObject
from zope.container.i18n import ZopeMessageFactory as _ from zope.container.i18n import ZopeMessageFactory as _ # NOQA
from zope.container.interfaces import IContainerNamesContainer from zope.container.interfaces import IContainerNamesContainer
from zope.container.interfaces import INameChooser from zope.container.interfaces import INameChooser
from zope.event import notify from zope.event import notify
...@@ -80,10 +80,10 @@ class Adding(BrowserView): ...@@ -80,10 +80,10 @@ class Adding(BrowserView):
content.id = name content.id = name
container._setObject(name, content) container._setObject(name, content)
self.contentName = name # Set the added object Name self.contentName = name # Set the added object Name
return container._getOb(name) return container._getOb(name)
contentName = None # usually set by Adding traverser contentName = None # usually set by Adding traverser
def nextURL(self): def nextURL(self):
"""See zope.browser.interfaces.IAdding""" """See zope.browser.interfaces.IAdding"""
...@@ -133,7 +133,7 @@ class Adding(BrowserView): ...@@ -133,7 +133,7 @@ class Adding(BrowserView):
view_name = type_name view_name = type_name
if queryMultiAdapter((self, self.request), if queryMultiAdapter((self, self.request),
name=view_name) is not None: name=view_name) is not None:
url = "%s/%s=%s" % ( url = "%s/%s=%s" % (
absoluteURL(self, self.request), type_name, id) absoluteURL(self, self.request), type_name, id)
self.request.response.redirect(url) self.request.response.redirect(url)
...@@ -176,10 +176,10 @@ class Adding(BrowserView): ...@@ -176,10 +176,10 @@ class Adding(BrowserView):
if not checkFactory(container, None, factory): if not checkFactory(container, None, factory):
continue continue
elif item['extra']['factory'] != item['action']: elif item['extra']['factory'] != item['action']:
item['has_custom_add_view']=True item['has_custom_add_view'] = True
result.append(item) result.append(item)
result.sort(lambda a, b: cmp(a['title'], b['title'])) result.sort(key=operator.itemgetter('title'))
return result return result
def isSingleMenuItem(self): def isSingleMenuItem(self):
...@@ -187,12 +187,12 @@ class Adding(BrowserView): ...@@ -187,12 +187,12 @@ class Adding(BrowserView):
return len(self.addingInfo()) == 1 return len(self.addingInfo()) == 1
def hasCustomAddView(self): def hasCustomAddView(self):
"This should be called only if there is `singleMenuItem` else return 0" "This should be called only if there is `singleMenuItem` else return 0"
if self.isSingleMenuItem(): if self.isSingleMenuItem():
menu_item = self.addingInfo()[0] menu_item = self.addingInfo()[0]
if 'has_custom_add_view' in menu_item: if 'has_custom_add_view' in menu_item:
return True return True
return False return False
class ContentAdding(Adding, SimpleItem): class ContentAdding(Adding, SimpleItem):
...@@ -215,13 +215,13 @@ class ObjectManagerNameChooser: ...@@ -215,13 +215,13 @@ class ObjectManagerNameChooser:
try: try:
name = name.encode('ascii') name = name.encode('ascii')
except UnicodeDecodeError: except UnicodeDecodeError:
raise UserError, "Id must contain only ASCII characters." raise UserError("Id must contain only ASCII characters.")
try: try:
self.context._checkId(name, allow_dup=False) self.context._checkId(name, allow_dup=False)
except BadRequest, e: except BadRequest as e:
msg = ' '.join(e.args) or "Id is in use or invalid" msg = ' '.join(e.args) or "Id is in use or invalid"
raise UserError, msg raise UserError(msg)
def chooseName(self, name, object): def chooseName(self, name, object):
if not name: if not name:
...@@ -230,7 +230,7 @@ class ObjectManagerNameChooser: ...@@ -230,7 +230,7 @@ class ObjectManagerNameChooser:
try: try:
name = name.encode('ascii') name = name.encode('ascii')
except UnicodeDecodeError: except UnicodeDecodeError:
raise UserError, "Id must contain only ASCII characters." raise UserError("Id must contain only ASCII characters.")
dot = name.rfind('.') dot = name.rfind('.')
if dot >= 0: if dot >= 0:
......
This diff is collapsed.
...@@ -27,9 +27,12 @@ from Products.PageTemplates.Expressions import createTrustedZopeEngine ...@@ -27,9 +27,12 @@ from Products.PageTemplates.Expressions import createTrustedZopeEngine
from Products.Five.bbb import AcquisitionBBB from Products.Five.bbb import AcquisitionBBB
_engine = createTrustedZopeEngine() _engine = createTrustedZopeEngine()
def getEngine(): def getEngine():
return _engine return _engine
class ViewPageTemplateFile(TrustedAppPT, PageTemplateFile): class ViewPageTemplateFile(TrustedAppPT, PageTemplateFile):
"""Page Template used as class variable of views defined as Python classes. """Page Template used as class variable of views defined as Python classes.
""" """
...@@ -57,7 +60,7 @@ class ViewPageTemplateFile(TrustedAppPT, PageTemplateFile): ...@@ -57,7 +60,7 @@ class ViewPageTemplateFile(TrustedAppPT, PageTemplateFile):
namespace, namespace,
showtal=getattr(debug_flags, 'showTAL', 0), showtal=getattr(debug_flags, 'showTAL', 0),
sourceAnnotations=getattr(debug_flags, 'sourceAnnotations', 0), sourceAnnotations=getattr(debug_flags, 'sourceAnnotations', 0),
) )
response = instance.request.response response = instance.request.response
if not response.getHeader("Content-Type"): if not response.getHeader("Content-Type"):
response.setHeader("Content-Type", self.content_type) response.setHeader("Content-Type", self.content_type)
...@@ -87,8 +90,8 @@ class ViewPageTemplateFile(TrustedAppPT, PageTemplateFile): ...@@ -87,8 +90,8 @@ class ViewPageTemplateFile(TrustedAppPT, PageTemplateFile):
root=root, root=root,
modules=SecureModuleImporter, modules=SecureModuleImporter,
traverse_subpath=[], # BBB, never really worked traverse_subpath=[], # BBB, never really worked
user = getSecurityManager().getUser() user=getSecurityManager().getUser(),
) )
return namespace return namespace
def __get__(self, instance, type): def __get__(self, instance, type):
...@@ -104,9 +107,10 @@ class ViewMapper(object): ...@@ -104,9 +107,10 @@ class ViewMapper(object):
return getMultiAdapter((self.ob, self.request), name=name) return getMultiAdapter((self.ob, self.request), name=name)
# When a view's template is accessed e.g. as template.view, a # When a view's template is accessed e.g. as template.view, a
# BoundPageTemplate object is retured. For BBB reasons, it needs to # BoundPageTemplate object is returned. For BBB reasons, it needs to
# support the aq_* methods and attributes known from Acquisition. For # support the aq_* methods and attributes known from Acquisition. For
# that it also needs to be locatable thru __parent__. # that it also needs to be locatable through __parent__.
class BoundPageTemplate(AcquisitionBBB): class BoundPageTemplate(AcquisitionBBB):
def __init__(self, pt, ob): def __init__(self, pt, ob):
......
...@@ -32,6 +32,7 @@ from Products.Five.browser import BrowserView ...@@ -32,6 +32,7 @@ from Products.Five.browser import BrowserView
_marker = object() _marker = object()
class Resource(object): class Resource(object):
"""A mixin that changes the URL-rendering of resources (__call__). """A mixin that changes the URL-rendering of resources (__call__).
...@@ -53,6 +54,7 @@ class Resource(object): ...@@ -53,6 +54,7 @@ class Resource(object):
name = '++resource++%s' % name name = '++resource++%s' % name
return "%s/%s" % (url, name) return "%s/%s" % (url, name)
class PageTemplateResource(Resource, BrowserView): class PageTemplateResource(Resource, BrowserView):
implements(IBrowserPublisher) implements(IBrowserPublisher)
...@@ -70,6 +72,7 @@ class PageTemplateResource(Resource, BrowserView): ...@@ -70,6 +72,7 @@ class PageTemplateResource(Resource, BrowserView):
pt = self.context pt = self.context
return pt(self.request) return pt(self.request)
class FileResource(Resource, zope.browserresource.file.FileResource): class FileResource(Resource, zope.browserresource.file.FileResource):
pass pass
...@@ -89,6 +92,7 @@ class ResourceFactory(object): ...@@ -89,6 +92,7 @@ class ResourceFactory(object):
resource = self.resource(self.__rsrc, request) resource = self.resource(self.__rsrc, request)
return resource return resource
def _PageTemplate(self, path, name): def _PageTemplate(self, path, name):
# PageTemplate doesn't take a name parameter, # PageTemplate doesn't take a name parameter,
# which makes it different from FileResource. # which makes it different from FileResource.
...@@ -97,18 +101,21 @@ def _PageTemplate(self, path, name): ...@@ -97,18 +101,21 @@ def _PageTemplate(self, path, name):
template.__name__ = name template.__name__ = name
return template return template
class PageTemplateResourceFactory(ResourceFactory): class PageTemplateResourceFactory(ResourceFactory):
"""A factory for Page Template resources""" """A factory for Page Template resources"""
factory = _PageTemplate factory = _PageTemplate
resource = PageTemplateResource resource = PageTemplateResource
class FileResourceFactory(ResourceFactory): class FileResourceFactory(ResourceFactory):
"""A factory for File resources""" """A factory for File resources"""
factory = File factory = File
resource = FileResource resource = FileResource
class ImageResourceFactory(ResourceFactory): class ImageResourceFactory(ResourceFactory):
"""A factory for Image resources""" """A factory for Image resources"""
...@@ -117,24 +124,25 @@ class ImageResourceFactory(ResourceFactory): ...@@ -117,24 +124,25 @@ class ImageResourceFactory(ResourceFactory):
# we only need this class a context for DirectoryResource # we only need this class a context for DirectoryResource
class Directory: class Directory(object):
def __init__(self, path, name): def __init__(self, path, name):
self.path = path self.path = path
self.__name__ = name self.__name__ = name
class DirectoryResource(Resource, class DirectoryResource(Resource,
zope.browserresource.directory.DirectoryResource): zope.browserresource.directory.DirectoryResource):
resource_factories = { resource_factories = {
'gif': ImageResourceFactory, 'gif': ImageResourceFactory,
'png': ImageResourceFactory, 'png': ImageResourceFactory,
'jpg': ImageResourceFactory, 'jpg': ImageResourceFactory,
'pt': PageTemplateResourceFactory, 'pt': PageTemplateResourceFactory,
'zpt': PageTemplateResourceFactory, 'zpt': PageTemplateResourceFactory,
'html': PageTemplateResourceFactory, 'html': PageTemplateResourceFactory,
'htm': PageTemplateResourceFactory, 'htm': PageTemplateResourceFactory,
} }
default_factory = FileResourceFactory default_factory = FileResourceFactory
...@@ -164,14 +172,15 @@ class DirectoryResource(Resource, ...@@ -164,14 +172,15 @@ class DirectoryResource(Resource,
resource = factory(name, filename)(self.request) resource = factory(name, filename)(self.request)
resource.__name__ = name resource.__name__ = name
resource.__parent__ = self resource.__parent__ = self
# We need to propagate security so that restrictedTraverse() will # We need to propagate security so that restrictedTraverse() will
# work # work
if hasattr(aq_base(self), '__roles__'): if hasattr(aq_base(self), '__roles__'):
resource.__roles__ = self.__roles__ resource.__roles__ = self.__roles__
return resource return resource
class DirectoryResourceFactory(ResourceFactory): class DirectoryResourceFactory(ResourceFactory):
factory = Directory factory = Directory
......
...@@ -26,6 +26,7 @@ from zope.contentprovider.interfaces import IContentProvider ...@@ -26,6 +26,7 @@ from zope.contentprovider.interfaces import IContentProvider
from Products.Five import BrowserView from Products.Five import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
class LegacyAttributes(BrowserView): class LegacyAttributes(BrowserView):
"""Make sure that those old aq_* attributes on Five BrowserViews """Make sure that those old aq_* attributes on Five BrowserViews
still work, in particular aq_chain, even though BrowserView may still work, in particular aq_chain, even though BrowserView may
...@@ -35,6 +36,7 @@ class LegacyAttributes(BrowserView): ...@@ -35,6 +36,7 @@ class LegacyAttributes(BrowserView):
def __call__(self): def __call__(self):
return repr([obj for obj in self.aq_chain]) return repr([obj for obj in self.aq_chain])
class ExplicitLegacyAttributes(Acquisition.Explicit): class ExplicitLegacyAttributes(Acquisition.Explicit):
"""Make sure that those old aq_* attributes work on browser views """Make sure that those old aq_* attributes work on browser views
that only inherit from Explicit as well.""" that only inherit from Explicit as well."""
...@@ -42,6 +44,7 @@ class ExplicitLegacyAttributes(Acquisition.Explicit): ...@@ -42,6 +44,7 @@ class ExplicitLegacyAttributes(Acquisition.Explicit):
def __call__(self): def __call__(self):
return repr([obj for obj in self.aq_chain]) return repr([obj for obj in self.aq_chain])
class LegacyTemplate(BrowserView): class LegacyTemplate(BrowserView):
template = ViewPageTemplateFile('falcon.pt') template = ViewPageTemplateFile('falcon.pt')
...@@ -49,6 +52,7 @@ class LegacyTemplate(BrowserView): ...@@ -49,6 +52,7 @@ class LegacyTemplate(BrowserView):
def __call__(self): def __call__(self):
return self.template() return self.template()
class LegacyTemplateTwo(BrowserView): class LegacyTemplateTwo(BrowserView):
def __init__(self, context, request): def __init__(self, context, request):
...@@ -60,21 +64,26 @@ class LegacyTemplateTwo(BrowserView): ...@@ -60,21 +64,26 @@ class LegacyTemplateTwo(BrowserView):
def __call__(self): def __call__(self):
return self.template() return self.template()
class Explicit(Acquisition.Explicit): class Explicit(Acquisition.Explicit):
def render(self): def render(self):
return 'Explicit' return 'Explicit'
class ExplicitWithTemplate(Acquisition.Explicit): class ExplicitWithTemplate(Acquisition.Explicit):
template = ViewPageTemplateFile('falcon.pt') template = ViewPageTemplateFile('falcon.pt')
class Implicit(Acquisition.Implicit): class Implicit(Acquisition.Implicit):
index_html = None # we don't want to acquire this! index_html = None # we don't want to acquire this!
def render(self): def render(self):
return 'Implicit' return 'Implicit'
class ImplicitWithTemplate(Acquisition.Implicit): class ImplicitWithTemplate(Acquisition.Implicit):
template = ViewPageTemplateFile('falcon.pt') template = ViewPageTemplateFile('falcon.pt')
...@@ -96,6 +105,7 @@ class ExplicitContentProvider(Acquisition.Explicit): ...@@ -96,6 +105,7 @@ class ExplicitContentProvider(Acquisition.Explicit):
def render(self): def render(self):
return 'Content provider inheriting from Explicit' return 'Content provider inheriting from Explicit'
class ExplicitViewlet(Acquisition.Explicit): class ExplicitViewlet(Acquisition.Explicit):
def __init__(self, context, request, view, manager): def __init__(self, context, request, view, manager):
...@@ -111,6 +121,7 @@ class ExplicitViewlet(Acquisition.Explicit): ...@@ -111,6 +121,7 @@ class ExplicitViewlet(Acquisition.Explicit):
def render(self): def render(self):
return 'Viewlet inheriting from Explicit' return 'Viewlet inheriting from Explicit'
class BrowserViewViewlet(BrowserView): class BrowserViewViewlet(BrowserView):
def __init__(self, context, request, view, manager): def __init__(self, context, request, view, manager):
...@@ -139,6 +150,7 @@ class LegacyNamespace(object): ...@@ -139,6 +150,7 @@ class LegacyNamespace(object):
def traverse(self, name, ignored): def traverse(self, name, ignored):
return LegacyNamespaceObject(name) return LegacyNamespaceObject(name)
class LegacyNamespaceObject(OFS.SimpleItem.SimpleItem): class LegacyNamespaceObject(OFS.SimpleItem.SimpleItem):
def __init__(self, name): def __init__(self, name):
......
...@@ -17,16 +17,19 @@ ...@@ -17,16 +17,19 @@
from zope.interface import Interface, implements from zope.interface import Interface, implements
from Products.Five import BrowserView from Products.Five import BrowserView
class IOne(Interface): class IOne(Interface):
"""This is an interface. """This is an interface.
""" """
class One(object): class One(object):
'A class' 'A class'
implements(IOne) implements(IOne)
class ViewOne(BrowserView): class ViewOne(BrowserView):
'Yet another class' 'Yet another class'
def my_method(self, arg1, arg2, kw1=None, kw2='D'): def my_method(self, arg1, arg2, kw1=None, kw2='D'):
print "CALLED %s %s %s %s" % (arg1, arg2, kw1, kw2) print("CALLED %s %s %s %s" % (arg1, arg2, kw1, kw2))
...@@ -15,8 +15,10 @@ ...@@ -15,8 +15,10 @@
""" """
from zope.i18nmessageid import MessageFactory from zope.i18nmessageid import MessageFactory
_ = MessageFactory('fivetest')
from Products.Five import BrowserView from Products.Five import BrowserView
_ = MessageFactory('fivetest')
class I18nView(BrowserView): class I18nView(BrowserView):
this_is_a_message = _(u'This is a message') this_is_a_message = _(u'This is a message')
...@@ -16,5 +16,6 @@ ...@@ -16,5 +16,6 @@
from zope.publisher.interfaces.browser import IDefaultBrowserLayer from zope.publisher.interfaces.browser import IDefaultBrowserLayer
class ITestSkin(IDefaultBrowserLayer): class ITestSkin(IDefaultBrowserLayer):
pass pass
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
"""Test AbsoluteURL """Test AbsoluteURL
""" """
def test_absoluteurl(): def test_absoluteurl():
"""This tests the absolute url view (IAbsoluteURL or @@absolute_url), """This tests the absolute url view (IAbsoluteURL or @@absolute_url),
in particular the breadcrumb functionality. in particular the breadcrumb functionality.
...@@ -83,6 +84,7 @@ def test_absoluteurl(): ...@@ -83,6 +84,7 @@ def test_absoluteurl():
>>> tearDown() >>> tearDown()
""" """
def test_suite(): def test_suite():
from Testing.ZopeTestCase import ZopeDocTestSuite from Testing.ZopeTestCase import ZopeDocTestSuite
return ZopeDocTestSuite() return ZopeDocTestSuite()
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
"""Test adding views """Test adding views
""" """
def test_suite(): def test_suite():
from Testing.ZopeTestCase import ZopeDocFileSuite from Testing.ZopeTestCase import ZopeDocFileSuite
return ZopeDocFileSuite('adding.txt', return ZopeDocFileSuite('adding.txt',
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
"""Unit tests for decode module. """Unit tests for decode module.
""" """
def test_processInputs(): def test_processInputs():
""" """
Testing processInputs Testing processInputs
...@@ -100,6 +101,7 @@ def test_processInputs(): ...@@ -100,6 +101,7 @@ def test_processInputs():
""" """
def test_suite(): def test_suite():
from doctest import DocTestSuite from doctest import DocTestSuite
return DocTestSuite() return DocTestSuite()
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
"""Test Default View functionality """Test Default View functionality
""" """
def test_default_view(): def test_default_view():
""" """
Test default view functionality Test default view functionality
...@@ -176,6 +177,7 @@ def test_default_method_args_marshalling(): ...@@ -176,6 +177,7 @@ def test_default_method_args_marshalling():
>>> cleanUp() >>> cleanUp()
""" """
def test_suite(): def test_suite():
from Testing.ZopeTestCase import FunctionalDocTestSuite from Testing.ZopeTestCase import FunctionalDocTestSuite
return FunctionalDocTestSuite() return FunctionalDocTestSuite()
...@@ -14,12 +14,13 @@ ...@@ -14,12 +14,13 @@
"""Unit tests for the i18n framework """Unit tests for the i18n framework
""" """
def test_zpt_i18n(): def test_zpt_i18n():
""" """
Test i18n functionality in ZPTs Test i18n functionality in ZPTs
>>> configure_zcml = ''' >>> configure_zcml = '''
... <configure ... <configure
... xmlns="http://namespaces.zope.org/zope" ... xmlns="http://namespaces.zope.org/zope"
... xmlns:browser="http://namespaces.zope.org/browser" ... xmlns:browser="http://namespaces.zope.org/browser"
... xmlns:i18n="http://namespaces.zope.org/i18n"> ... xmlns:i18n="http://namespaces.zope.org/i18n">
...@@ -81,6 +82,7 @@ def test_zpt_i18n(): ...@@ -81,6 +82,7 @@ def test_zpt_i18n():
>>> tearDown() >>> tearDown()
""" """
def test_suite(): def test_suite():
from Testing.ZopeTestCase import FunctionalDocTestSuite from Testing.ZopeTestCase import FunctionalDocTestSuite
from doctest import ELLIPSIS from doctest import ELLIPSIS
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
"""Test browser menus """Test browser menus
""" """
def test_menu(): def test_menu():
""" """
Test menus Test menus
...@@ -39,7 +40,7 @@ def test_menu(): ...@@ -39,7 +40,7 @@ def test_menu():
>>> request = TestRequest() >>> request = TestRequest()
>>> menu = getMenu('testmenu', self.folder, request) >>> menu = getMenu('testmenu', self.folder, request)
It should have It should have
>>> len(menu) >>> len(menu)
4 4
...@@ -149,7 +150,7 @@ def test_menu(): ...@@ -149,7 +150,7 @@ def test_menu():
'description': u'This is a test menu item', 'description': u'This is a test menu item',
'extra': None, 'extra': None,
'icon': None, 'icon': None,
'selected': u'', 'selected': u'',
'submenu': None, 'submenu': None,
'title': u'Test Menu Item 2'} 'title': u'Test Menu Item 2'}
...@@ -169,6 +170,7 @@ def test_menu(): ...@@ -169,6 +170,7 @@ def test_menu():
>>> tearDown() >>> tearDown()
""" """
def test_suite(): def test_suite():
from Testing.ZopeTestCase import ZopeDocTestSuite from Testing.ZopeTestCase import ZopeDocTestSuite
return ZopeDocTestSuite() return ZopeDocTestSuite()
import unittest import unittest
class ViewMixinForTemplatesTests(unittest.TestCase): class ViewMixinForTemplatesTests(unittest.TestCase):
def _getTargetClass(self): def _getTargetClass(self):
...@@ -41,7 +42,7 @@ class ViewMixinForTemplatesTests(unittest.TestCase): ...@@ -41,7 +42,7 @@ class ViewMixinForTemplatesTests(unittest.TestCase):
index.macros = {} index.macros = {}
index.macros['aaa'] = aaa = object() index.macros['aaa'] = aaa = object()
self.assertTrue(view['aaa'] is aaa) self.assertTrue(view['aaa'] is aaa)
def test__getitem__gives_shortcut_to_index_macros(self): def test__getitem__gives_shortcut_to_index_macros(self):
view = self._makeOne() view = self._makeOne()
view.index = index = DummyTemplate() view.index = index = DummyTemplate()
...@@ -77,18 +78,15 @@ class ViewMixinForTemplatesTests(unittest.TestCase): ...@@ -77,18 +78,15 @@ class ViewMixinForTemplatesTests(unittest.TestCase):
self.assertEqual(index._called_with, (('abc',), {'foo': 'bar'})) self.assertEqual(index._called_with, (('abc',), {'foo': 'bar'}))
class DummyContext: class DummyContext(object):
pass pass
class DummyRequest:
class DummyRequest(object):
pass pass
class DummyTemplate: class DummyTemplate:
def __call__(self, *args, **kw): def __call__(self, *args, **kw):
self._called_with = (args, kw) self._called_with = (args, kw)
return self return self
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(ViewMixinForTemplatesTests),
))
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
""" """
import unittest import unittest
def test_view_with_unwrapped_context(): def test_view_with_unwrapped_context():
""" """
It may be desirable when writing tests for views themselves to It may be desirable when writing tests for views themselves to
...@@ -63,6 +64,7 @@ def test_view_with_unwrapped_context(): ...@@ -63,6 +64,7 @@ def test_view_with_unwrapped_context():
>>> tearDown() >>> tearDown()
""" """
def test_suite(): def test_suite():
from Testing.ZopeTestCase import FunctionalDocFileSuite from Testing.ZopeTestCase import FunctionalDocFileSuite
from Testing.ZopeTestCase import ZopeDocFileSuite from Testing.ZopeTestCase import ZopeDocFileSuite
...@@ -74,4 +76,4 @@ def test_suite(): ...@@ -74,4 +76,4 @@ def test_suite():
package='Products.Five.browser.tests'), package='Products.Five.browser.tests'),
FunctionalDocFileSuite('aqlegacy_ftest.txt', FunctionalDocFileSuite('aqlegacy_ftest.txt',
package='Products.Five.browser.tests'), package='Products.Five.browser.tests'),
)) ))
...@@ -37,8 +37,6 @@ class ViewPageTemplateFileTests(unittest.TestCase): ...@@ -37,8 +37,6 @@ class ViewPageTemplateFileTests(unittest.TestCase):
def test_pt_getEngine(self): def test_pt_getEngine(self):
from zope.tales.expressions import DeferExpr from zope.tales.expressions import DeferExpr
from zope.tales.expressions import NotExpr from zope.tales.expressions import NotExpr
from zope.tales.expressions import PathExpr
from zope.tales.expressions import Undefs
from zope.tales.pythonexpr import PythonExpr from zope.tales.pythonexpr import PythonExpr
from zope.contentprovider.tales import TALESProviderExpression from zope.contentprovider.tales import TALESProviderExpression
from Products.PageTemplates.DeferExpr import LazyExpr from Products.PageTemplates.DeferExpr import LazyExpr
...@@ -85,8 +83,6 @@ class ViewPageTemplateFileTests(unittest.TestCase): ...@@ -85,8 +83,6 @@ class ViewPageTemplateFileTests(unittest.TestCase):
self.assertEqual(namespace['user'].getId(), 'a_user') self.assertEqual(namespace['user'].getId(), 'a_user')
def test_pt_getContext_w_physicalRoot(self): def test_pt_getContext_w_physicalRoot(self):
from Products.Five.browser.pagetemplatefile import ViewMapper
from Products.PageTemplates.Expressions import SecureModuleImporter
from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManagement import newSecurityManager
newSecurityManager(None, DummyUser('a_user')) newSecurityManager(None, DummyUser('a_user'))
context = DummyContext() context = DummyContext()
...@@ -99,8 +95,6 @@ class ViewPageTemplateFileTests(unittest.TestCase): ...@@ -99,8 +95,6 @@ class ViewPageTemplateFileTests(unittest.TestCase):
self.assertTrue(namespace['root'] is root) self.assertTrue(namespace['root'] is root)
def test_pt_getContext_w_ignored_kw(self): def test_pt_getContext_w_ignored_kw(self):
from Products.Five.browser.pagetemplatefile import ViewMapper
from Products.PageTemplates.Expressions import SecureModuleImporter
from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManagement import newSecurityManager
newSecurityManager(None, DummyUser('a_user')) newSecurityManager(None, DummyUser('a_user'))
context = DummyContext() context = DummyContext()
...@@ -112,8 +106,6 @@ class ViewPageTemplateFileTests(unittest.TestCase): ...@@ -112,8 +106,6 @@ class ViewPageTemplateFileTests(unittest.TestCase):
self.assertFalse('foo' in namespace['options']) self.assertFalse('foo' in namespace['options'])
def test_pt_getContext_w_args_kw(self): def test_pt_getContext_w_args_kw(self):
from Products.Five.browser.pagetemplatefile import ViewMapper
from Products.PageTemplates.Expressions import SecureModuleImporter
from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManagement import newSecurityManager
newSecurityManager(None, DummyUser('a_user')) newSecurityManager(None, DummyUser('a_user'))
context = DummyContext() context = DummyContext()
...@@ -124,8 +116,6 @@ class ViewPageTemplateFileTests(unittest.TestCase): ...@@ -124,8 +116,6 @@ class ViewPageTemplateFileTests(unittest.TestCase):
self.assertEqual(namespace['args'], ('bar', 'baz')) self.assertEqual(namespace['args'], ('bar', 'baz'))
def test_pt_getContext_w_options_kw(self): def test_pt_getContext_w_options_kw(self):
from Products.Five.browser.pagetemplatefile import ViewMapper
from Products.PageTemplates.Expressions import SecureModuleImporter
from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManagement import newSecurityManager
newSecurityManager(None, DummyUser('a_user')) newSecurityManager(None, DummyUser('a_user'))
context = DummyContext() context = DummyContext()
...@@ -149,20 +139,22 @@ class ViewPageTemplateFileTests(unittest.TestCase): ...@@ -149,20 +139,22 @@ class ViewPageTemplateFileTests(unittest.TestCase):
context = DummyContext() context = DummyContext()
request = DummyRequest() request = DummyRequest()
response = request.response = DummyResponse( response = request.response = DummyResponse(
{'Content-Type': 'text/xhtml'}) {'Content-Type': 'text/xhtml'})
view = self._makeView(context, request) view = self._makeView(context, request)
vptf = self._makeOne('templates/dirpage1.pt') vptf = self._makeOne('templates/dirpage1.pt')
body = vptf(view) vptf(view)
self.assertEqual(response._headers['Content-Type'], 'text/xhtml') self.assertEqual(response._headers['Content-Type'], 'text/xhtml')
def test___get___(self): def test___get___(self):
from Products.Five.browser.pagetemplatefile import BoundPageTemplate from Products.Five.browser.pagetemplatefile import BoundPageTemplate
template = self._makeOne('templates/dirpage1.pt') template = self._makeOne('templates/dirpage1.pt')
class Foo:
class Foo(object):
def __init__(self, context, request): def __init__(self, context, request):
self.context = context self.context = context
self.request = request self.request = request
bar = template bar = template
context = DummyContext() context = DummyContext()
request = DummyRequest() request = DummyRequest()
foo = Foo(context, request) foo = Foo(context, request)
...@@ -171,6 +163,7 @@ class ViewPageTemplateFileTests(unittest.TestCase): ...@@ -171,6 +163,7 @@ class ViewPageTemplateFileTests(unittest.TestCase):
self.assertTrue(bound.im_func is template) self.assertTrue(bound.im_func is template)
self.assertTrue(bound.im_self is foo) self.assertTrue(bound.im_self is foo)
class ViewMapperTests(unittest.TestCase): class ViewMapperTests(unittest.TestCase):
def setUp(self): def setUp(self):
...@@ -200,14 +193,17 @@ class ViewMapperTests(unittest.TestCase): ...@@ -200,14 +193,17 @@ class ViewMapperTests(unittest.TestCase):
def test___getitem___hit(self): def test___getitem___hit(self):
from zope.interface import Interface from zope.interface import Interface
from zope.component import provideAdapter from zope.component import provideAdapter
def _adapt(context, request): def _adapt(context, request):
return self return self
provideAdapter(_adapt, (None, None), Interface, name='test') provideAdapter(_adapt, (None, None), Interface, name='test')
mapper = self._makeOne() mapper = self._makeOne()
self.assertTrue(mapper['test'] is self) self.assertTrue(mapper['test'] is self)
_marker = object() _marker = object()
class BoundPageTemplateTests(unittest.TestCase): class BoundPageTemplateTests(unittest.TestCase):
def _getTargetClass(self): def _getTargetClass(self):
...@@ -269,13 +265,16 @@ DIRPAGE1 = """\ ...@@ -269,13 +265,16 @@ DIRPAGE1 = """\
</html> </html>
""" """
class DummyContext:
class DummyContext(object):
pass pass
class DummyRequest:
class DummyRequest(object):
debug = object() debug = object()
class DummyResponse:
class DummyResponse(object):
def __init__(self, headers=None): def __init__(self, headers=None):
if headers is None: if headers is None:
headers = {} headers = {}
...@@ -287,30 +286,31 @@ class DummyResponse: ...@@ -287,30 +286,31 @@ class DummyResponse:
def setHeader(self, name, value): def setHeader(self, name, value):
self._headers[name] = value self._headers[name] = value
class DummyTemplate:
class DummyTemplate(object):
filename = 'dummy.pt' filename = 'dummy.pt'
def __init__(self, macros=None): def __init__(self, macros=None):
if macros is None: if macros is None:
macros = {} macros = {}
self.macros = macros self.macros = macros
def __call__(self, im_self, *args, **kw): def __call__(self, im_self, *args, **kw):
self._called_with = (im_self, args, kw) self._called_with = (im_self, args, kw)
return '<h1>Dummy</h1>' return '<h1>Dummy</h1>'
class DummyView:
class DummyView(object):
def __init__(self, context, request): def __init__(self, context, request):
self.context = context self.context = context
self.request = request self.request = request
class DummyUser:
class DummyUser(object):
def __init__(self, name): def __init__(self, name):
self._name = name self._name = name
def getId(self): def getId(self):
return self._name return self._name
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(ViewPageTemplateFileTests),
unittest.makeSuite(ViewMapperTests),
unittest.makeSuite(BoundPageTemplateTests),
))
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
"""Test browser pages """Test browser pages
""" """
def test_suite(): def test_suite():
from Testing.ZopeTestCase import FunctionalDocFileSuite from Testing.ZopeTestCase import FunctionalDocFileSuite
return FunctionalDocFileSuite('provider.txt', return FunctionalDocFileSuite('provider.txt',
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
"""Test default view recursion """Test default view recursion
""" """
def test_recursion(): def test_recursion():
""" """
Test recursion Test recursion
...@@ -59,6 +60,7 @@ def test_recursion(): ...@@ -59,6 +60,7 @@ def test_recursion():
>>> cleanUp() >>> cleanUp()
""" """
def test_suite(): def test_suite():
from Testing.ZopeTestCase import ZopeDocTestSuite from Testing.ZopeTestCase import ZopeDocTestSuite
return ZopeDocTestSuite() return ZopeDocTestSuite()
...@@ -15,12 +15,13 @@ ...@@ -15,12 +15,13 @@
""" """
import unittest import unittest
def test_suite(): def test_suite():
from Testing.ZopeTestCase import FunctionalDocFileSuite from Testing.ZopeTestCase import FunctionalDocFileSuite
from Testing.ZopeTestCase import ZopeDocFileSuite from Testing.ZopeTestCase import ZopeDocFileSuite
return unittest.TestSuite(( return unittest.TestSuite((
ZopeDocFileSuite('resource.txt', ZopeDocFileSuite('resource.txt',
package='Products.Five.browser.tests'), package='Products.Five.browser.tests'),
FunctionalDocFileSuite('resource_ftest.txt', FunctionalDocFileSuite('resource_ftest.txt',
package='Products.Five.browser.tests'), package='Products.Five.browser.tests'),
)) ))
...@@ -18,7 +18,7 @@ def checkRestricted(folder, psbody): ...@@ -18,7 +18,7 @@ def checkRestricted(folder, psbody):
addPythonScript(folder, 'ps', body=psbody) addPythonScript(folder, 'ps', body=psbody)
try: try:
folder.ps() folder.ps()
except Unauthorized, e: except Unauthorized as e:
raise AssertionError(e) raise AssertionError(e)
...@@ -94,7 +94,7 @@ def test_resource_restricted_code(): ...@@ -94,7 +94,7 @@ def test_resource_restricted_code():
>>> self.folder.restrictedTraverse('++resource++fivetest_resources/resource.txt') is not None >>> self.folder.restrictedTraverse('++resource++fivetest_resources/resource.txt') is not None
True True
>>> self.folder.restrictedTraverse('++resource++fivetest_resources/resource_subdir/resource.txt') is not None >>> self.folder.restrictedTraverse('++resource++fivetest_resources/resource_subdir/resource.txt') is not None
True True
...@@ -104,6 +104,7 @@ def test_resource_restricted_code(): ...@@ -104,6 +104,7 @@ def test_resource_restricted_code():
>>> tearDown() >>> tearDown()
""" """
def test_view_restricted_code(): def test_view_restricted_code():
""" """
Let's register a quite large amount of test pages: Let's register a quite large amount of test pages:
...@@ -128,7 +129,7 @@ def test_view_restricted_code(): ...@@ -128,7 +129,7 @@ def test_view_restricted_code():
>>> protected_view_names = [ >>> protected_view_names = [
... 'eagle.txt', 'falcon.html', 'owl.html', 'flamingo.html', ... 'eagle.txt', 'falcon.html', 'owl.html', 'flamingo.html',
... 'condor.html', 'permission_view'] ... 'condor.html', 'permission_view']
>>>
>>> public_view_names = [ >>> public_view_names = [
... 'public_attribute_page', ... 'public_attribute_page',
... 'public_template_page', ... 'public_template_page',
...@@ -181,7 +182,7 @@ def test_view_restricted_code(): ...@@ -181,7 +182,7 @@ def test_view_restricted_code():
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
try: try:
import Products.PythonScripts import Products.PythonScripts # NOQA
except ImportError: except ImportError:
pass pass
else: else:
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
"""Test browser pages """Test browser pages
""" """
def test_suite(): def test_suite():
from Testing.ZopeTestCase import FunctionalDocFileSuite from Testing.ZopeTestCase import FunctionalDocFileSuite
return FunctionalDocFileSuite('skin.txt', return FunctionalDocFileSuite('skin.txt',
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
"""Test Five-traversable classes """Test Five-traversable classes
""" """
class SimpleClass(object): class SimpleClass(object):
"""Class with no __bobo_traverse__.""" """Class with no __bobo_traverse__."""
...@@ -48,7 +49,7 @@ def test_traversable(): ...@@ -48,7 +49,7 @@ def test_traversable():
... xmlns:meta="http://namespaces.zope.org/meta" ... xmlns:meta="http://namespaces.zope.org/meta"
... xmlns:browser="http://namespaces.zope.org/browser" ... xmlns:browser="http://namespaces.zope.org/browser"
... xmlns:five="http://namespaces.zope.org/five"> ... xmlns:five="http://namespaces.zope.org/five">
... ...
... <!-- make the zope2.Public permission work --> ... <!-- make the zope2.Public permission work -->
... <meta:redefinePermission from="zope2.Public" to="zope.Public" /> ... <meta:redefinePermission from="zope2.Public" to="zope.Public" />
... ...
...@@ -129,7 +130,7 @@ def test_traversable(): ...@@ -129,7 +130,7 @@ def test_traversable():
Five's traversable monkeypatches the __bobo_traverse__ method to do view Five's traversable monkeypatches the __bobo_traverse__ method to do view
lookup and then delegates back to the original __bobo_traverse__ or direct lookup and then delegates back to the original __bobo_traverse__ or direct
attribute/item lookup to do normal lookup. In the Zope 2 ZPublisher, an attribute/item lookup to do normal lookup. In the Zope 2 ZPublisher, an
object with a __bobo_traverse__ will not do attribute lookup unless the object with a __bobo_traverse__ will not do attribute lookup unless the
__bobo_traverse__ method itself does it (i.e. the __bobo_traverse__ is the __bobo_traverse__ method itself does it (i.e. the __bobo_traverse__ is the
only element used for traversal lookup). Let's demonstrate: only element used for traversal lookup). Let's demonstrate:
...@@ -179,6 +180,7 @@ def test_traversable(): ...@@ -179,6 +180,7 @@ def test_traversable():
False False
""" """
def test_view_doesnt_shadow_attribute(): def test_view_doesnt_shadow_attribute():
""" """
Test that views don't shadow attributes, e.g. items in a folder. Test that views don't shadow attributes, e.g. items in a folder.
...@@ -265,7 +267,7 @@ def test_view_doesnt_shadow_attribute(): ...@@ -265,7 +267,7 @@ def test_view_doesnt_shadow_attribute():
However, acquired attributes *should* be shadowed. See discussion on However, acquired attributes *should* be shadowed. See discussion on
http://codespeak.net/pipermail/z3-five/2006q2/001474.html http://codespeak.net/pipermail/z3-five/2006q2/001474.html
>>> manage_addIndexSimpleContent(self.folder, 'mouse', 'Mouse') >>> manage_addIndexSimpleContent(self.folder, 'mouse', 'Mouse')
>>> print http(r''' >>> print http(r'''
... GET /test_folder_1_/ftf/mouse HTTP/1.1 ... GET /test_folder_1_/ftf/mouse HTTP/1.1
...@@ -273,13 +275,14 @@ def test_view_doesnt_shadow_attribute(): ...@@ -273,13 +275,14 @@ def test_view_doesnt_shadow_attribute():
HTTP/1.1 200 OK HTTP/1.1 200 OK
... ...
The mouse has been eaten by the eagle The mouse has been eaten by the eagle
Clean up: Clean up:
>>> from zope.component.testing import tearDown >>> from zope.component.testing import tearDown
>>> tearDown() >>> tearDown()
""" """
def test_suite(): def test_suite():
from Testing.ZopeTestCase import FunctionalDocTestSuite from Testing.ZopeTestCase import FunctionalDocTestSuite
return FunctionalDocTestSuite() return FunctionalDocTestSuite()
...@@ -7,7 +7,7 @@ def test_check_permission(): ...@@ -7,7 +7,7 @@ def test_check_permission():
work. work.
>>> configure_zcml = ''' >>> configure_zcml = '''
... <configure ... <configure
... xmlns="http://namespaces.zope.org/zope" ... xmlns="http://namespaces.zope.org/zope"
... xmlns:browser="http://namespaces.zope.org/browser"> ... xmlns:browser="http://namespaces.zope.org/browser">
... <securityPolicy ... <securityPolicy
...@@ -53,6 +53,7 @@ def test_check_permission(): ...@@ -53,6 +53,7 @@ def test_check_permission():
""" """
def test_allowed_interface(): def test_allowed_interface():
"""This test demonstrates that allowed_interface security declarations work """This test demonstrates that allowed_interface security declarations work
as expected. as expected.
...@@ -143,6 +144,7 @@ def test_allowed_interface(): ...@@ -143,6 +144,7 @@ def test_allowed_interface():
>>> tearDown() >>> tearDown()
""" """
def test_suite(): def test_suite():
from Testing.ZopeTestCase import FunctionalDocTestSuite from Testing.ZopeTestCase import FunctionalDocTestSuite
from doctest import ELLIPSIS from doctest import ELLIPSIS
......
from zope.publisher.browser import BrowserView from zope.publisher.browser import BrowserView
from zope.security.management import checkPermission from zope.security.management import checkPermission
class Zope3SecurityView(BrowserView): class Zope3SecurityView(BrowserView):
def __call__(self, permission): def __call__(self, permission):
......
...@@ -32,6 +32,7 @@ from ZPublisher.BeforeTraverse import unregisterBeforeTraverse ...@@ -32,6 +32,7 @@ from ZPublisher.BeforeTraverse import unregisterBeforeTraverse
from zope.component.hooks import setHooks from zope.component.hooks import setHooks
setHooks() setHooks()
def findSite(obj, iface=ISite): def findSite(obj, iface=ISite):
"""Find a site by walking up the object hierarchy, supporting both """Find a site by walking up the object hierarchy, supporting both
the ``ILocation`` API and Zope 2 Acquisition.""" the ``ILocation`` API and Zope 2 Acquisition."""
...@@ -39,6 +40,7 @@ def findSite(obj, iface=ISite): ...@@ -39,6 +40,7 @@ def findSite(obj, iface=ISite):
obj = aq_parent(aq_inner(obj)) obj = aq_parent(aq_inner(obj))
return obj return obj
@zope.component.adapter(zope.interface.Interface) @zope.component.adapter(zope.interface.Interface)
@zope.interface.implementer(IComponentLookup) @zope.interface.implementer(IComponentLookup)
def siteManagerAdapter(ob): def siteManagerAdapter(ob):
...@@ -51,6 +53,7 @@ def siteManagerAdapter(ob): ...@@ -51,6 +53,7 @@ def siteManagerAdapter(ob):
return zope.component.getGlobalSiteManager() return zope.component.getGlobalSiteManager()
return site.getSiteManager() return site.getSiteManager()
class LocalSiteHook(ExtensionClass.Base): class LocalSiteHook(ExtensionClass.Base):
def __call__(self, container, request): def __call__(self, container, request):
...@@ -58,6 +61,7 @@ class LocalSiteHook(ExtensionClass.Base): ...@@ -58,6 +61,7 @@ class LocalSiteHook(ExtensionClass.Base):
HOOK_NAME = '__local_site_hook__' HOOK_NAME = '__local_site_hook__'
def enableSite(obj, iface=ISite): def enableSite(obj, iface=ISite):
"""Install __before_traverse__ hook for Local Site """Install __before_traverse__ hook for Local Site
""" """
...@@ -73,6 +77,7 @@ def enableSite(obj, iface=ISite): ...@@ -73,6 +77,7 @@ def enableSite(obj, iface=ISite):
zope.interface.alsoProvides(obj, iface) zope.interface.alsoProvides(obj, iface)
def disableSite(obj, iface=ISite): def disableSite(obj, iface=ISite):
"""Remove __before_traverse__ hook for Local Site """Remove __before_traverse__ hook for Local Site
""" """
......
...@@ -27,9 +27,9 @@ class ObjectManagerSiteView(BrowserView): ...@@ -27,9 +27,9 @@ class ObjectManagerSiteView(BrowserView):
def update(self): def update(self):
form = self.request.form form = self.request.form
if form.has_key('MAKESITE'): if 'MAKESITE' in form:
self.makeSite() self.makeSite()
elif form.has_key('UNMAKESITE'): elif 'UNMAKESITE' in form:
self.unmakeSite() self.unmakeSite()
def isSite(self): def isSite(self):
...@@ -41,7 +41,7 @@ class ObjectManagerSiteView(BrowserView): ...@@ -41,7 +41,7 @@ class ObjectManagerSiteView(BrowserView):
enableSite(self.context, iface=IObjectManagerSite) enableSite(self.context, iface=IObjectManagerSite)
#TODO in the future we'll have to walk up to other site # TODO in the future we'll have to walk up to other site
# managers and put them in the bases # managers and put them in the bases
components = PersistentComponents() components = PersistentComponents()
components.__bases__ = (base,) components.__bases__ = (base,)
......
...@@ -19,5 +19,4 @@ from OFS.interfaces import IObjectManager ...@@ -19,5 +19,4 @@ from OFS.interfaces import IObjectManager
class IObjectManagerSite(IObjectManager, ISite): class IObjectManagerSite(IObjectManager, ISite):
"""Object manager that is also a site.""" """Object manager that is also a site."""
...@@ -24,4 +24,4 @@ def test_suite(): ...@@ -24,4 +24,4 @@ def test_suite():
DocFileSuite('component.txt', package="Products.Five.component"), DocFileSuite('component.txt', package="Products.Five.component"),
FunctionalDocFileSuite('makesite.txt', FunctionalDocFileSuite('makesite.txt',
package="Products.Five.component"), package="Products.Five.component"),
]) ])
...@@ -21,6 +21,7 @@ from Products.Five import fivemethod, isFiveMethod ...@@ -21,6 +21,7 @@ from Products.Five import fivemethod, isFiveMethod
# holds classes that were monkeyed with; for clean up # holds classes that were monkeyed with; for clean up
_monkied = [] _monkied = []
@fivemethod @fivemethod
def get_size(self): def get_size(self):
size = ISized(self, None) size = ISized(self, None)
...@@ -32,6 +33,7 @@ def get_size(self): ...@@ -32,6 +33,7 @@ def get_size(self):
if method is not None: if method is not None:
return self.__five_original_get_size() return self.__five_original_get_size()
def classSizable(class_): def classSizable(class_):
"""Monkey the class to be sizable through Five""" """Monkey the class to be sizable through Five"""
# tuck away the original method if necessary # tuck away the original method if necessary
...@@ -41,14 +43,15 @@ def classSizable(class_): ...@@ -41,14 +43,15 @@ def classSizable(class_):
# remember class for clean up # remember class for clean up
_monkied.append(class_) _monkied.append(class_)
def sizable(_context, class_): def sizable(_context, class_):
_context.action( _context.action(
discriminator = ('five:sizable', class_), discriminator=('five:sizable', class_),
callable = classSizable, callable=classSizable,
args=(class_,) args=(class_,)
) )
# clean up code
def killMonkey(class_, name, fallback, attr=None): def killMonkey(class_, name, fallback, attr=None):
"""Die monkey, die!""" """Die monkey, die!"""
method = getattr(class_, name, None) method = getattr(class_, name, None)
...@@ -70,14 +73,17 @@ def killMonkey(class_, name, fallback, attr=None): ...@@ -70,14 +73,17 @@ def killMonkey(class_, name, fallback, attr=None):
except (AttributeError, KeyError): except (AttributeError, KeyError):
pass pass
def unsizable(class_): def unsizable(class_):
"""Restore class's initial state with respect to being sizable""" """Restore class's initial state with respect to being sizable"""
killMonkey(class_, 'get_size', '__five_original_get_size') killMonkey(class_, 'get_size', '__five_original_get_size')
def cleanUp(): def cleanUp():
for class_ in _monkied: for class_ in _monkied:
unsizable(class_) unsizable(class_)
from zope.testing.cleanup import addCleanUp
from zope.testing.cleanup import addCleanUp # NOQA
addCleanUp(cleanUp) addCleanUp(cleanUp)
del addCleanUp del addCleanUp
...@@ -18,9 +18,8 @@ import zope.interface ...@@ -18,9 +18,8 @@ import zope.interface
import zope.component import zope.component
from Products.Five.browser import BrowserView 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(object):
class Macros:
zope.interface.implements(zope.interface.common.mapping.IItemMapping) zope.interface.implements(zope.interface.common.mapping.IItemMapping)
macro_pages = () macro_pages = ()
...@@ -28,24 +27,27 @@ class Macros: ...@@ -28,24 +27,27 @@ class Macros:
'view': 'page', 'view': 'page',
'dialog': 'page', 'dialog': 'page',
'addingdialog': 'page' 'addingdialog': 'page'
} }
def __getitem__(self, key): def __getitem__(self, key):
key = self.aliases.get(key, key) key = self.aliases.get(key, key)
context = self.context context = self.context
request = self.request request = self.request
for name in self.macro_pages: for name in self.macro_pages:
page = zope.component.getMultiAdapter((context, request), name=name) page = zope.component.getMultiAdapter(
(context, request), name=name)
try: try:
v = page[key] v = page[key]
except KeyError: except KeyError:
pass pass
else: else:
return v return v
raise KeyError, key raise KeyError(key)
class StandardMacros(BrowserView, Macros): class StandardMacros(BrowserView, Macros):
macro_pages = ('five_template', macro_pages = (
'widget_macros', 'five_template',
'form_macros',) 'widget_macros',
'form_macros',
)
...@@ -16,8 +16,11 @@ ...@@ -16,8 +16,11 @@
from Products.Five import StandardMacros as BaseMacros from Products.Five import StandardMacros as BaseMacros
class StandardMacros(BaseMacros): class StandardMacros(BaseMacros):
macro_pages = ('bird_macros', 'dog_macros') macro_pages = ('bird_macros', 'dog_macros')
aliases = {'flying':'birdmacro', aliases = {
'walking':'dogmacro'} 'flying': 'birdmacro',
'walking': 'dogmacro',
}
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
"""Test standard macros """Test standard macros
""" """
def test_standard_macros(): def test_standard_macros():
"""Test standard macros """Test standard macros
...@@ -27,7 +28,7 @@ def test_standard_macros(): ...@@ -27,7 +28,7 @@ def test_standard_macros():
>>> import Products.Five.skin.tests >>> import Products.Five.skin.tests
>>> from Zope2.App import zcml >>> from Zope2.App import zcml
>>> zcml.load_config('configure.zcml', package=Products.Five) >>> zcml.load_config('configure.zcml', package=Products.Five)
>>> zcml.load_config('configure.zcml', package=Products.Five.skin.tests) >>> zcml.load_config('configure.zcml', package=Products.Five.skin.tests)
Test macro access through our flavour of StandardMacros. First, Test macro access through our flavour of StandardMacros. First,
when looking up a non-existing macro, we get a KeyError: when looking up a non-existing macro, we get a KeyError:
...@@ -71,6 +72,7 @@ def test_standard_macros(): ...@@ -71,6 +72,7 @@ def test_standard_macros():
>>> tearDown() >>> tearDown()
""" """
def test_suite(): def test_suite():
from Testing.ZopeTestCase import ZopeDocTestSuite from Testing.ZopeTestCase import ZopeDocTestSuite
return ZopeDocTestSuite() return ZopeDocTestSuite()
Five tests
==========
All you have to do is type::
$ bin/zopectl test -s Products.Five
to run the Five tests.
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
from zope.interface import implements, Interface from zope.interface import implements, Interface
from zope.component import adapts from zope.component import adapts
class IAdaptable(Interface): class IAdaptable(Interface):
"""This is a Zope interface. """This is a Zope interface.
""" """
...@@ -24,6 +25,7 @@ class IAdaptable(Interface): ...@@ -24,6 +25,7 @@ class IAdaptable(Interface):
"""This method will be adapted """This method will be adapted
""" """
class IAdapted(Interface): class IAdapted(Interface):
"""The interface we adapt to. """The interface we adapt to.
""" """
...@@ -32,22 +34,26 @@ class IAdapted(Interface): ...@@ -32,22 +34,26 @@ class IAdapted(Interface):
"""A method to adapt. """A method to adapt.
""" """
class IOrigin(Interface): class IOrigin(Interface):
"""Something we'll adapt""" """Something we'll adapt"""
class IDestination(Interface): class IDestination(Interface):
"""The result of an adaption""" """The result of an adaption"""
def method(): def method():
"""Do something""" """Do something"""
class Adaptable:
class Adaptable(object):
implements(IAdaptable) implements(IAdaptable)
def method(self): def method(self):
return "The method" return "The method"
class Adapter:
class Adapter(object):
implements(IAdapted) implements(IAdapted)
adapts(IAdaptable) adapts(IAdaptable)
...@@ -57,10 +63,12 @@ class Adapter: ...@@ -57,10 +63,12 @@ class Adapter:
def adaptedMethod(self): def adaptedMethod(self):
return "Adapted: %s" % self.context.method() return "Adapted: %s" % self.context.method()
class Origin:
class Origin(object):
implements(IOrigin) implements(IOrigin)
class OriginalAdapter:
class OriginalAdapter(object):
implements(IDestination) implements(IDestination)
def __init__(self, context): def __init__(self, context):
...@@ -69,7 +77,8 @@ class OriginalAdapter: ...@@ -69,7 +77,8 @@ class OriginalAdapter:
def method(self): def method(self):
return "Original" return "Original"
class OverrideAdapter:
class OverrideAdapter(object):
implements(IDestination) implements(IDestination)
def __init__(self, context): def __init__(self, context):
......
##############################################################################
#
# Copyright (c) 2005 Zope Foundation 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.
#
##############################################################################
"""Boiler plate test module
"""
def test_boilerplate():
"""
>>> from zope.component.testing import setUp, tearDown
>>> setUp()
>>> import Products.Five.tests
>>> from Zope2.App import zcml
>>> zcml.load_config('boilerplate.zcml', Products.Five.tests)
>>> 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()
"""
def test_suite():
from Testing.ZopeTestCase import ZopeDocTestSuite
return ZopeDocTestSuite()
...@@ -16,16 +16,20 @@ ...@@ -16,16 +16,20 @@
from zope.interface import Interface from zope.interface import Interface
class One(object): class One(object):
'A class' 'A class'
class Two(object): class Two(object):
'Another class' 'Another class'
class IOne(Interface): class IOne(Interface):
"""This is a Zope interface. """This is a Zope interface.
""" """
class ITwo(Interface): class ITwo(Interface):
"""This is another Zope interface. """This is another Zope interface.
""" """
...@@ -18,27 +18,28 @@ from zope.interface import Interface ...@@ -18,27 +18,28 @@ from zope.interface import Interface
from zope.configuration.fields import GlobalObject from zope.configuration.fields import GlobalObject
from zope.schema import TextLine from zope.schema import TextLine
class IParrotDirective(Interface): class IParrotDirective(Interface):
"""State that a class implements something. """State that a class implements something.
""" """
class_ = GlobalObject( class_ = GlobalObject(
title=u"Class", title=u"Class",
required=True required=True,
) )
name = TextLine( name = TextLine(
title=u"Name", title=u"Name",
description=u"The parrots name.", description=u"The parrots name.",
required=True required=True,
) )
def parrot(_context, class_, name): def parrot(_context, class_, name):
parrot = class_() parrot = class_()
parrot.pineForFjords() parrot.pineForFjords()
class NorwegianBlue(object): class NorwegianBlue(object):
def pineForFjords(self): def pineForFjords(self):
return "This parrot is no more!" return "This parrot is no more!"
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
"""Test the basic ZCML directives """Test the basic ZCML directives
""" """
def test_directives(): def test_directives():
""" """
Test ZCML directives Test ZCML directives
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
from zope.component.testing import setUp, tearDown from zope.component.testing import setUp, tearDown
def test_directive(): def test_directive():
""" """
Test the i18n directive. First, we need to register the ZCML Test the i18n directive. First, we need to register the ZCML
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
from zope.interface import implements from zope.interface import implements
from zope.size.interfaces import ISized from zope.size.interfaces import ISized
class SimpleContentSize(object): class SimpleContentSize(object):
"""Size for ``SimpleContent`` objects.""" """Size for ``SimpleContent`` objects."""
implements(ISized) implements(ISized)
...@@ -30,6 +31,7 @@ class SimpleContentSize(object): ...@@ -30,6 +31,7 @@ class SimpleContentSize(object):
def sizeForDisplay(self): def sizeForDisplay(self):
return "What is the meaning of life?" return "What is the meaning of life?"
class FancyContentSize(object): class FancyContentSize(object):
"""Size for ``SimpleContent`` objects.""" """Size for ``SimpleContent`` objects."""
implements(ISized) implements(ISized)
...@@ -43,6 +45,7 @@ class FancyContentSize(object): ...@@ -43,6 +45,7 @@ class FancyContentSize(object):
def sizeForDisplay(self): def sizeForDisplay(self):
return "That's not the meaning of life!" return "That's not the meaning of life!"
def test_size(): def test_size():
""" """
Test size adapters Test size adapters
...@@ -94,6 +97,7 @@ def test_size(): ...@@ -94,6 +97,7 @@ def test_size():
>>> tearDown() >>> tearDown()
""" """
def test_suite(): def test_suite():
from Testing.ZopeTestCase import ZopeDocTestSuite from Testing.ZopeTestCase import ZopeDocTestSuite
return ZopeDocTestSuite() return ZopeDocTestSuite()
...@@ -14,7 +14,9 @@ ...@@ -14,7 +14,9 @@
"""Test helpers """Test helpers
""" """
from Products.Five.tests.testing.folder import FiveTraversableFolder from Products.Five.tests.testing.folder import ( # NOQA
from Products.Five.tests.testing.folder import manage_addFiveTraversableFolder FiveTraversableFolder,
from Products.Five.tests.testing.folder import manage_addNoVerifyPasteFolder manage_addFiveTraversableFolder,
from Products.Five.tests.testing.folder import NoVerifyPasteFolder manage_addNoVerifyPasteFolder,
NoVerifyPasteFolder,
)
...@@ -22,9 +22,11 @@ from OFS.SimpleItem import SimpleItem ...@@ -22,9 +22,11 @@ from OFS.SimpleItem import SimpleItem
from zope.interface import implements from zope.interface import implements
from zope.interface import Interface from zope.interface import Interface
class IFancyContent(Interface): class IFancyContent(Interface):
pass pass
class FancyAttribute(Explicit): class FancyAttribute(Explicit):
"""Doc test fanatics""" """Doc test fanatics"""
...@@ -40,6 +42,7 @@ class FancyAttribute(Explicit): ...@@ -40,6 +42,7 @@ class FancyAttribute(Explicit):
InitializeClass(FancyAttribute) InitializeClass(FancyAttribute)
class FancyContent(SimpleItem): class FancyContent(SimpleItem):
"""A class that already comes with its own __bobo_traverse__ handler. """A class that already comes with its own __bobo_traverse__ handler.
Quite fancy indeed. Quite fancy indeed.
...@@ -65,13 +68,14 @@ class FancyContent(SimpleItem): ...@@ -65,13 +68,14 @@ class FancyContent(SimpleItem):
InitializeClass(FancyContent) InitializeClass(FancyContent)
# A copy of the above class used to demonstrate some baseline behavior
class NonTraversableFancyContent(SimpleItem): class NonTraversableFancyContent(SimpleItem):
"""A class that already comes with its own __bobo_traverse__ handler. """A class that already comes with its own __bobo_traverse__ handler.
Quite fancy indeed. Quite fancy indeed.
It also comes with its own get_size method. It also comes with its own get_size method.
""" """
# A copy of the above class used to demonstrate some baseline behavior.
implements(IFancyContent) implements(IFancyContent)
meta_type = "Fancy Content" meta_type = "Fancy Content"
...@@ -91,11 +95,13 @@ class NonTraversableFancyContent(SimpleItem): ...@@ -91,11 +95,13 @@ class NonTraversableFancyContent(SimpleItem):
InitializeClass(NonTraversableFancyContent) InitializeClass(NonTraversableFancyContent)
def manage_addFancyContent(self, id, REQUEST=None): def manage_addFancyContent(self, id, REQUEST=None):
"""Add the fancy fancy content.""" """Add the fancy fancy content."""
id = self._setObject(id, FancyContent(id)) id = self._setObject(id, FancyContent(id))
return '' return ''
def manage_addNonTraversableFancyContent(self, id, REQUEST=None): def manage_addNonTraversableFancyContent(self, id, REQUEST=None):
"""Add the fancy fancy content.""" """Add the fancy fancy content."""
id = self._setObject(id, NonTraversableFancyContent(id)) id = self._setObject(id, NonTraversableFancyContent(id))
......
...@@ -18,6 +18,7 @@ from OFS.Folder import Folder ...@@ -18,6 +18,7 @@ from OFS.Folder import Folder
from OFS.interfaces import IFolder from OFS.interfaces import IFolder
from zope.interface import implements from zope.interface import implements
class NoVerifyPasteFolder(Folder): class NoVerifyPasteFolder(Folder):
"""Folder that does not perform paste verification. """Folder that does not perform paste verification.
Used by test_events Used by test_events
...@@ -25,17 +26,20 @@ class NoVerifyPasteFolder(Folder): ...@@ -25,17 +26,20 @@ class NoVerifyPasteFolder(Folder):
def _verifyObjectPaste(self, object, validate_src=1): def _verifyObjectPaste(self, object, validate_src=1):
pass pass
def manage_addNoVerifyPasteFolder(container, id, title=''): def manage_addNoVerifyPasteFolder(container, id, title=''):
container._setObject(id, NoVerifyPasteFolder()) container._setObject(id, NoVerifyPasteFolder())
folder = container[id] folder = container[id]
folder.id = id folder.id = id
folder.title = title folder.title = title
class FiveTraversableFolder(Folder): class FiveTraversableFolder(Folder):
"""Folder that is five-traversable """Folder that is five-traversable
""" """
implements(IFolder) implements(IFolder)
def manage_addFiveTraversableFolder(container, id, title=''): def manage_addFiveTraversableFolder(container, id, title=''):
container._setObject(id, FiveTraversableFolder()) container._setObject(id, FiveTraversableFolder())
folder = container[id] folder = container[id]
......
def somemethod(self): def somemethod(self):
print "Executed somemethod" print("Executed somemethod")
def initialize(context): def initialize(context):
print "pythonproduct2 initialized" print("pythonproduct2 initialized")
...@@ -21,15 +21,19 @@ from OFS.SimpleItem import SimpleItem ...@@ -21,15 +21,19 @@ from OFS.SimpleItem import SimpleItem
from zope.interface import implements from zope.interface import implements
from zope.interface import Interface from zope.interface import Interface
class ISimpleContent(Interface): class ISimpleContent(Interface):
pass pass
class ICallableSimpleContent(ISimpleContent): class ICallableSimpleContent(ISimpleContent):
pass pass
class IIndexSimpleContent(ISimpleContent): class IIndexSimpleContent(ISimpleContent):
pass pass
class SimpleContent(SimpleItem): class SimpleContent(SimpleItem):
implements(ISimpleContent) implements(ISimpleContent)
...@@ -52,6 +56,7 @@ class SimpleContent(SimpleItem): ...@@ -52,6 +56,7 @@ class SimpleContent(SimpleItem):
InitializeClass(SimpleContent) InitializeClass(SimpleContent)
class CallableSimpleContent(SimpleItem): class CallableSimpleContent(SimpleItem):
"""A Viewable piece of content""" """A Viewable piece of content"""
implements(ICallableSimpleContent) implements(ICallableSimpleContent)
...@@ -64,6 +69,7 @@ class CallableSimpleContent(SimpleItem): ...@@ -64,6 +69,7 @@ class CallableSimpleContent(SimpleItem):
InitializeClass(CallableSimpleContent) InitializeClass(CallableSimpleContent)
class IndexSimpleContent(SimpleItem): class IndexSimpleContent(SimpleItem):
"""A Viewable piece of content""" """A Viewable piece of content"""
implements(IIndexSimpleContent) implements(IIndexSimpleContent)
...@@ -76,14 +82,17 @@ class IndexSimpleContent(SimpleItem): ...@@ -76,14 +82,17 @@ class IndexSimpleContent(SimpleItem):
InitializeClass(IndexSimpleContent) InitializeClass(IndexSimpleContent)
def manage_addSimpleContent(self, id, title, REQUEST=None): def manage_addSimpleContent(self, id, title, REQUEST=None):
"""Add the simple content.""" """Add the simple content."""
self._setObject(id, SimpleContent(id, title)) self._setObject(id, SimpleContent(id, title))
def manage_addCallableSimpleContent(self, id, title, REQUEST=None): def manage_addCallableSimpleContent(self, id, title, REQUEST=None):
"""Add the viewable simple content.""" """Add the viewable simple content."""
self._setObject(id, CallableSimpleContent(id, title)) self._setObject(id, CallableSimpleContent(id, title))
def manage_addIndexSimpleContent(self, id, title, REQUEST=None): def manage_addIndexSimpleContent(self, id, title, REQUEST=None):
"""Add the viewable simple content.""" """Add the viewable simple content."""
self._setObject(id, IndexSimpleContent(id, title)) self._setObject(id, IndexSimpleContent(id, title))
...@@ -17,8 +17,7 @@ ...@@ -17,8 +17,7 @@
from Products.Five.utilities.interfaces import IMarkerInterfaces from Products.Five.utilities.interfaces import IMarkerInterfaces
class EditView: class EditView(object):
"""Marker interface edit view. """Marker interface edit view.
""" """
...@@ -36,8 +35,9 @@ class EditView: ...@@ -36,8 +35,9 @@ class EditView:
return self.index() return self.index()
def _getLinkToInterfaceDetailsView(self, interfaceName): def _getLinkToInterfaceDetailsView(self, interfaceName):
return (self.context_url + return (self.context_url + (
'/views-details.html?iface=%s&type=zope.publisher.interfaces.browser.IBrowserRequest' % interfaceName) '/views-details.html?iface=%s&type=zope.publisher.'
'interfaces.browser.IBrowserRequest' % interfaceName))
def _getNameLinkDicts(self, interfaceNames): def _getNameLinkDicts(self, interfaceNames):
return [dict(name=name, return [dict(name=name,
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
"""Unit tests for marker interface views. """Unit tests for marker interface views.
""" """
def test_editview(): def test_editview():
""" """
Set everything up: Set everything up:
...@@ -84,6 +85,7 @@ def test_editview(): ...@@ -84,6 +85,7 @@ def test_editview():
>>> tearDown() >>> tearDown()
""" """
def test_suite(): def test_suite():
from Testing.ZopeTestCase import ZopeDocTestSuite from Testing.ZopeTestCase import ZopeDocTestSuite
return ZopeDocTestSuite() return ZopeDocTestSuite()
...@@ -26,6 +26,7 @@ from zope.component.interface import searchInterface ...@@ -26,6 +26,7 @@ from zope.component.interface import searchInterface
from interfaces import IMarkerInterfaces from interfaces import IMarkerInterfaces
def interfaceStringCheck(f): def interfaceStringCheck(f):
def wrapper(ob, interface): def wrapper(ob, interface):
if isinstance(interface, str): if isinstance(interface, str):
...@@ -33,11 +34,13 @@ def interfaceStringCheck(f): ...@@ -33,11 +34,13 @@ def interfaceStringCheck(f):
return f(ob, interface) return f(ob, interface)
return wrapper return wrapper
def mark(ob, interface): def mark(ob, interface):
directlyProvides(ob, directlyProvidedBy(ob), interface) directlyProvides(ob, directlyProvidedBy(ob), interface)
def erase(ob, interface): def erase(ob, interface):
directlyProvides(ob, directlyProvidedBy(ob)-interface) directlyProvides(ob, directlyProvidedBy(ob) - interface)
mark = interfaceStringCheck(mark) mark = interfaceStringCheck(mark)
erase = interfaceStringCheck(erase) erase = interfaceStringCheck(erase)
...@@ -74,8 +77,8 @@ class MarkerInterfacesAdapter(object): ...@@ -74,8 +77,8 @@ class MarkerInterfacesAdapter(object):
todo.append(base) todo.append(base)
markers = self._getDirectMarkersOf(interface) markers = self._getDirectMarkersOf(interface)
for interface in markers: for interface in markers:
if (interface not in results if (interface not in results and
and not interface.providedBy(self.context)): not interface.providedBy(self.context)):
results.append(interface) results.append(interface)
todo += markers todo += markers
return tuple(results) return tuple(results)
......
# A package for viewlet support
\ No newline at end of file
...@@ -369,7 +369,7 @@ specified attribute: ...@@ -369,7 +369,7 @@ specified attribute:
Traceback (most recent call last): Traceback (most recent call last):
... ...
ZopeXMLConfigurationError: File "<string>", line 3.2-9.8 ZopeXMLConfigurationError: File "<string>", line 3.2-9.8
ConfigurationError: The provided class doesn't have the specified attribute ConfigurationError: The provided class doesn't have the specified attribute.
================================ ================================
Viewlet Directive Security Viewlet Directive Security
......
...@@ -23,6 +23,7 @@ from zope.viewlet.manager import ViewletManagerBase as origManagerBase ...@@ -23,6 +23,7 @@ from zope.viewlet.manager import ViewletManagerBase as origManagerBase
from Products.Five.browser.pagetemplatefile import ZopeTwoPageTemplateFile from Products.Five.browser.pagetemplatefile import ZopeTwoPageTemplateFile
class ViewletManagerBase(origManagerBase): class ViewletManagerBase(origManagerBase):
"""A base class for Viewlet managers to work in Zope2""" """A base class for Viewlet managers to work in Zope2"""
...@@ -38,14 +39,14 @@ class ViewletManagerBase(origManagerBase): ...@@ -38,14 +39,14 @@ class ViewletManagerBase(origManagerBase):
# If the viewlet was not found, then raise a lookup error # If the viewlet was not found, then raise a lookup error
if viewlet is None: if viewlet is None:
raise zope.interface.interfaces.ComponentLookupError( raise zope.interface.interfaces.ComponentLookupError(
'No provider with name `%s` found.' %name) 'No provider with name `%s` found.' % name)
# If the viewlet cannot be accessed, then raise an # If the viewlet cannot be accessed, then raise an
# unauthorized error # unauthorized error
if not guarded_hasattr(viewlet, 'render'): if not guarded_hasattr(viewlet, 'render'):
raise zope.security.interfaces.Unauthorized( raise zope.security.interfaces.Unauthorized(
'You are not authorized to access the provider ' 'You are not authorized to access the provider '
'called `%s`.' %name) 'called `%s`.' % name)
# Return the viewlet. # Return the viewlet.
return viewlet return viewlet
...@@ -73,7 +74,12 @@ class ViewletManagerBase(origManagerBase): ...@@ -73,7 +74,12 @@ class ViewletManagerBase(origManagerBase):
# By default, use the standard Python way of doing sorting. Unwrap the # By default, use the standard Python way of doing sorting. Unwrap the
# objects first so that they are sorted as expected. This is dumb # objects first so that they are sorted as expected. This is dumb
# but it allows the tests to have deterministic results. # but it allows the tests to have deterministic results.
return sorted(viewlets, lambda x, y: cmp(aq_base(x[1]), aq_base(y[1])))
def _key(info):
return aq_base(info[1])
return sorted(viewlets, key=_key)
def ViewletManager(name, interface, template=None, bases=()): def ViewletManager(name, interface, template=None, bases=()):
attrDict = {'__name__': name} attrDict = {'__name__': name}
......
...@@ -31,11 +31,12 @@ from AccessControl.security import protectName ...@@ -31,11 +31,12 @@ from AccessControl.security import protectName
from Products.Five.viewlet import manager from Products.Five.viewlet import manager
from Products.Five.viewlet import viewlet from Products.Five.viewlet import viewlet
def viewletManagerDirective( def viewletManagerDirective(
_context, name, permission, _context, name, permission,
for_=Interface, layer=IDefaultBrowserLayer, view=IBrowserView, for_=Interface, layer=IDefaultBrowserLayer, view=IBrowserView,
provides=interfaces.IViewletManager, class_=None, template=None, provides=interfaces.IViewletManager, class_=None, template=None,
allowed_interface=None, allowed_attributes=None): allowed_interface=None, allowed_attributes=None):
# If class is not given we use the basic viewlet manager. # If class is not given we use the basic viewlet manager.
if class_ is None: if class_ is None:
...@@ -69,36 +70,37 @@ def viewletManagerDirective( ...@@ -69,36 +70,37 @@ def viewletManagerDirective(
# register a viewlet manager # register a viewlet manager
_context.action( _context.action(
discriminator = ('viewletManager', for_, layer, view, name), discriminator=('viewletManager', for_, layer, view, name),
callable = zcml.handler, callable=zcml.handler,
args = ('registerAdapter', args=('registerAdapter',
new_class, (for_, layer, view), provides, name, new_class, (for_, layer, view), provides, name,
_context.info),) _context.info),
)
_context.action( _context.action(
discriminator = ('five:protectClass', new_class), discriminator=('five:protectClass', new_class),
callable = protectClass, callable=protectClass,
args = (new_class, permission) args=(new_class, permission),
) )
if allowed_attributes: if allowed_attributes:
for attr in allowed_attributes: for attr in allowed_attributes:
_context.action( _context.action(
discriminator = ('five:protectName', new_class, attr), discriminator=('five:protectName', new_class, attr),
callable = protectName, callable=protectName,
args = (new_class, attr, permission) args=(new_class, attr, permission),
) )
_context.action( _context.action(
discriminator = ('five:initialize:class', new_class), discriminator=('five:initialize:class', new_class),
callable = InitializeClass, callable=InitializeClass,
args = (new_class,) args=(new_class, ),
) )
def viewletDirective( def viewletDirective(
_context, name, permission, _context, name, permission,
for_=Interface, layer=IDefaultBrowserLayer, view=IBrowserView, for_=Interface, layer=IDefaultBrowserLayer, view=IBrowserView,
manager=interfaces.IViewletManager, class_=None, template=None, manager=interfaces.IViewletManager, class_=None, template=None,
attribute='render', allowed_interface=None, allowed_attributes=None, attribute='render', allowed_interface=None,
**kwargs): allowed_attributes=None, **kwargs):
# Either the class or template must be specified. # Either the class or template must be specified.
if not (class_ or template): if not (class_ or template):
...@@ -135,8 +137,8 @@ def viewletDirective( ...@@ -135,8 +137,8 @@ def viewletDirective(
if attribute != 'render': if attribute != 'render':
if not hasattr(class_, attribute): if not hasattr(class_, attribute):
raise ConfigurationError( raise ConfigurationError(
"The provided class doesn't have the specified attribute " "The provided class doesn't have the specified attribute."
) )
if template: if template:
# Create a new class for the viewlet template and class. # Create a new class for the viewlet template and class.
new_class = viewlet.SimpleViewletClass( new_class = viewlet.SimpleViewletClass(
...@@ -165,26 +167,26 @@ def viewletDirective( ...@@ -165,26 +167,26 @@ def viewletDirective(
# register viewlet # register viewlet
_context.action( _context.action(
discriminator = ('viewlet', for_, layer, view, manager, name), discriminator=('viewlet', for_, layer, view, manager, name),
callable = zcml.handler, callable=zcml.handler,
args = ('registerAdapter', args=('registerAdapter',
new_class, (for_, layer, view, manager), new_class, (for_, layer, view, manager),
interfaces.IViewlet, name, _context.info),) interfaces.IViewlet, name, _context.info),
)
_context.action( _context.action(
discriminator = ('five:protectClass', new_class), discriminator=('five:protectClass', new_class),
callable = protectClass, callable=protectClass,
args = (new_class, permission) args=(new_class, permission)
) )
if allowed_attributes: if allowed_attributes:
for attr in allowed_attributes: for attr in allowed_attributes:
_context.action( _context.action(
discriminator = ('five:protectName', new_class, attr), discriminator=('five:protectName', new_class, attr),
callable = protectName, callable=protectName,
args = (new_class, attr, permission) args=(new_class, attr, permission)
) )
_context.action( _context.action(
discriminator = ('five:initialize:class', new_class), discriminator=('five:initialize:class', new_class),
callable = InitializeClass, callable=InitializeClass,
args = (new_class,) args=(new_class,)
) )
...@@ -21,54 +21,64 @@ from zope.interface import implements ...@@ -21,54 +21,64 @@ from zope.interface import implements
from zope.viewlet import interfaces from zope.viewlet import interfaces
from OFS.SimpleItem import SimpleItem from OFS.SimpleItem import SimpleItem
class Content(SimpleItem): class Content(SimpleItem):
implements(Interface) implements(Interface)
class UnitTestSecurityPolicy: class UnitTestSecurityPolicy:
""" """
Stub out the existing security policy for unit testing purposes. Stub out the existing security policy for unit testing purposes.
""" """
# # Standard SecurityPolicy interface
# Standard SecurityPolicy interface def validate(self,
# accessed=None,
def validate( self container=None,
, accessed=None name=None,
, container=None value=None,
, name=None context=None,
, value=None roles=None,
, context=None *args, **kw):
, roles=None
, *args
, **kw):
return 1 return 1
def checkPermission( self, permission, object, context) : def checkPermission(self, permission, object, context):
return 1 return 1
class ILeftColumn(interfaces.IViewletManager): class ILeftColumn(interfaces.IViewletManager):
"""Left column of my page.""" """Left column of my page."""
class INewColumn(interfaces.IViewletManager): class INewColumn(interfaces.IViewletManager):
"""Left column of my page.""" """Left column of my page."""
class WeightBasedSorting(object): class WeightBasedSorting(object):
def sort(self, viewlets): def sort(self, viewlets):
return sorted(viewlets, def _key(info):
lambda x, y: cmp(x[1].weight, y[1].weight)) return getattr(info[1], 'weight', 0)
return sorted(viewlets, key=_key)
class Weather(object): class Weather(object):
weight = 0 weight = 0
class Stock(object): class Stock(object):
weight = 0 weight = 0
def getStockTicker(self): def getStockTicker(self):
return u'SRC $5.19' return u'SRC $5.19'
class Sport(object): class Sport(object):
weight = 0 weight = 0
def __call__(self): def __call__(self):
return u'Red Sox vs. White Sox' return u'Red Sox vs. White Sox'
class DynamicTempBox(object): class DynamicTempBox(object):
weight = 0 weight = 0
city = {'name': 'Los Angeles, CA', 'temp': 78} city = {'name': 'Los Angeles, CA', 'temp': 78}
...@@ -78,4 +88,4 @@ def test_suite(): ...@@ -78,4 +88,4 @@ def test_suite():
return unittest.TestSuite([ return unittest.TestSuite([
FunctionalDocFileSuite('README.txt'), FunctionalDocFileSuite('README.txt'),
FunctionalDocFileSuite('directives.txt'), FunctionalDocFileSuite('directives.txt'),
]) ])
...@@ -19,19 +19,22 @@ import zope.viewlet.viewlet ...@@ -19,19 +19,22 @@ import zope.viewlet.viewlet
from Products.Five.bbb import AcquisitionBBB from Products.Five.bbb import AcquisitionBBB
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
class ViewletBase(zope.viewlet.viewlet.ViewletBase, AcquisitionBBB): class ViewletBase(zope.viewlet.viewlet.ViewletBase, AcquisitionBBB):
pass pass
class SimpleAttributeViewlet(zope.viewlet.viewlet.SimpleAttributeViewlet, class SimpleAttributeViewlet(zope.viewlet.viewlet.SimpleAttributeViewlet,
AcquisitionBBB): AcquisitionBBB):
pass pass
class simple(zope.viewlet.viewlet.simple): class simple(zope.viewlet.viewlet.simple):
# We need to ensure that the proper __init__ is called. # We need to ensure that the proper __init__ is called.
__init__ = ViewletBase.__init__.im_func __init__ = ViewletBase.__init__.im_func
def SimpleViewletClass(template, bases=(), attributes=None,
name=u''): def SimpleViewletClass(template, bases=(), attributes=None, name=u''):
"""A function that can be used to generate a viewlet from a set of """A function that can be used to generate a viewlet from a set of
information. information.
""" """
...@@ -39,8 +42,8 @@ def SimpleViewletClass(template, bases=(), attributes=None, ...@@ -39,8 +42,8 @@ def SimpleViewletClass(template, bases=(), attributes=None,
# Create the base class hierarchy # Create the base class hierarchy
bases += (simple, ViewletBase) bases += (simple, ViewletBase)
attrs = {'index' : ViewPageTemplateFile(template), attrs = {'index': ViewPageTemplateFile(template),
'__name__' : name} '__name__': name}
if attributes: if attributes:
attrs.update(attributes) attrs.update(attributes)
...@@ -53,14 +56,14 @@ def SimpleViewletClass(template, bases=(), attributes=None, ...@@ -53,14 +56,14 @@ def SimpleViewletClass(template, bases=(), attributes=None,
class ResourceViewletBase(zope.viewlet.viewlet.ResourceViewletBase): class ResourceViewletBase(zope.viewlet.viewlet.ResourceViewletBase):
pass pass
def JavaScriptViewlet(path): def JavaScriptViewlet(path):
"""Create a viewlet that can simply insert a javascript link.""" """Create a viewlet that can simply insert a javascript link."""
src = os.path.join(os.path.dirname(__file__), 'javascript_viewlet.pt') src = os.path.join(os.path.dirname(__file__), 'javascript_viewlet.pt')
klass = type('JavaScriptViewlet', klass = type('JavaScriptViewlet',
(ResourceViewletBase, ViewletBase), (ResourceViewletBase, ViewletBase),
{'index': ViewPageTemplateFile(src), {'index': ViewPageTemplateFile(src), '_path': path})
'_path': path})
return klass return klass
...@@ -68,15 +71,16 @@ def JavaScriptViewlet(path): ...@@ -68,15 +71,16 @@ def JavaScriptViewlet(path):
class CSSResourceViewletBase(zope.viewlet.viewlet.CSSResourceViewletBase): class CSSResourceViewletBase(zope.viewlet.viewlet.CSSResourceViewletBase):
pass pass
def CSSViewlet(path, media="all", rel="stylesheet"): def CSSViewlet(path, media="all", rel="stylesheet"):
"""Create a viewlet that can simply insert a javascript link.""" """Create a viewlet that can simply insert a javascript link."""
src = os.path.join(os.path.dirname(__file__), 'css_viewlet.pt') src = os.path.join(os.path.dirname(__file__), 'css_viewlet.pt')
klass = type('CSSViewlet', klass = type('CSSViewlet',
(CSSResourceViewletBase, ViewletBase), (CSSResourceViewletBase, ViewletBase),
{'index': ViewPageTemplateFile(src), {'index': ViewPageTemplateFile(src),
'_path': path, '_path': path,
'_media':media, '_media': media,
'_rel':rel}) '_rel': rel})
return klass return klass
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment