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 @@
"""Initialize the Five product
"""
# public API provided by Five
# usage: from Products.Five import <something>
from Products.Five.browser import BrowserView
from Products.Five.skin.standardmacros import StandardMacros
from Products.Five.browser import BrowserView # NOQA
from Products.Five.skin.standardmacros import StandardMacros # NOQA
# some convenience methods/decorators
def fivemethod(func):
func.__five_method__ = True
return func
def isFiveMethod(m):
return hasattr(m, '__five_method__')
......@@ -19,7 +19,7 @@ factory screen.
(original: zope.app.container.browser.adding)
"""
__docformat__ = 'restructuredtext'
import operator
from zope.browser.interfaces import IAdding
from zope.browsermenu.menu import getMenu
......@@ -30,7 +30,7 @@ from zope.component import queryUtility
from zope.component.interfaces import IFactory
from zope.container.constraints import checkFactory
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 INameChooser
from zope.event import notify
......@@ -80,10 +80,10 @@ class Adding(BrowserView):
content.id = name
container._setObject(name, content)
self.contentName = name # Set the added object Name
self.contentName = name # Set the added object Name
return container._getOb(name)
contentName = None # usually set by Adding traverser
contentName = None # usually set by Adding traverser
def nextURL(self):
"""See zope.browser.interfaces.IAdding"""
......@@ -133,7 +133,7 @@ class Adding(BrowserView):
view_name = type_name
if queryMultiAdapter((self, self.request),
name=view_name) is not None:
name=view_name) is not None:
url = "%s/%s=%s" % (
absoluteURL(self, self.request), type_name, id)
self.request.response.redirect(url)
......@@ -176,10 +176,10 @@ class Adding(BrowserView):
if not checkFactory(container, None, factory):
continue
elif item['extra']['factory'] != item['action']:
item['has_custom_add_view']=True
item['has_custom_add_view'] = True
result.append(item)
result.sort(lambda a, b: cmp(a['title'], b['title']))
result.sort(key=operator.itemgetter('title'))
return result
def isSingleMenuItem(self):
......@@ -187,12 +187,12 @@ class Adding(BrowserView):
return len(self.addingInfo()) == 1
def hasCustomAddView(self):
"This should be called only if there is `singleMenuItem` else return 0"
if self.isSingleMenuItem():
menu_item = self.addingInfo()[0]
if 'has_custom_add_view' in menu_item:
return True
return False
"This should be called only if there is `singleMenuItem` else return 0"
if self.isSingleMenuItem():
menu_item = self.addingInfo()[0]
if 'has_custom_add_view' in menu_item:
return True
return False
class ContentAdding(Adding, SimpleItem):
......@@ -215,13 +215,13 @@ class ObjectManagerNameChooser:
try:
name = name.encode('ascii')
except UnicodeDecodeError:
raise UserError, "Id must contain only ASCII characters."
raise UserError("Id must contain only ASCII characters.")
try:
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"
raise UserError, msg
raise UserError(msg)
def chooseName(self, name, object):
if not name:
......@@ -230,7 +230,7 @@ class ObjectManagerNameChooser:
try:
name = name.encode('ascii')
except UnicodeDecodeError:
raise UserError, "Id must contain only ASCII characters."
raise UserError("Id must contain only ASCII characters.")
dot = name.rfind('.')
if dot >= 0:
......
This diff is collapsed.
......@@ -27,9 +27,12 @@ from Products.PageTemplates.Expressions import createTrustedZopeEngine
from Products.Five.bbb import AcquisitionBBB
_engine = createTrustedZopeEngine()
def getEngine():
return _engine
class ViewPageTemplateFile(TrustedAppPT, PageTemplateFile):
"""Page Template used as class variable of views defined as Python classes.
"""
......@@ -57,7 +60,7 @@ class ViewPageTemplateFile(TrustedAppPT, PageTemplateFile):
namespace,
showtal=getattr(debug_flags, 'showTAL', 0),
sourceAnnotations=getattr(debug_flags, 'sourceAnnotations', 0),
)
)
response = instance.request.response
if not response.getHeader("Content-Type"):
response.setHeader("Content-Type", self.content_type)
......@@ -87,8 +90,8 @@ class ViewPageTemplateFile(TrustedAppPT, PageTemplateFile):
root=root,
modules=SecureModuleImporter,
traverse_subpath=[], # BBB, never really worked
user = getSecurityManager().getUser()
)
user=getSecurityManager().getUser(),
)
return namespace
def __get__(self, instance, type):
......@@ -104,9 +107,10 @@ class ViewMapper(object):
return getMultiAdapter((self.ob, self.request), name=name)
# 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
# that it also needs to be locatable thru __parent__.
# that it also needs to be locatable through __parent__.
class BoundPageTemplate(AcquisitionBBB):
def __init__(self, pt, ob):
......
......@@ -32,6 +32,7 @@ from Products.Five.browser import BrowserView
_marker = object()
class Resource(object):
"""A mixin that changes the URL-rendering of resources (__call__).
......@@ -53,6 +54,7 @@ class Resource(object):
name = '++resource++%s' % name
return "%s/%s" % (url, name)
class PageTemplateResource(Resource, BrowserView):
implements(IBrowserPublisher)
......@@ -70,6 +72,7 @@ class PageTemplateResource(Resource, BrowserView):
pt = self.context
return pt(self.request)
class FileResource(Resource, zope.browserresource.file.FileResource):
pass
......@@ -89,6 +92,7 @@ class ResourceFactory(object):
resource = self.resource(self.__rsrc, request)
return resource
def _PageTemplate(self, path, name):
# PageTemplate doesn't take a name parameter,
# which makes it different from FileResource.
......@@ -97,18 +101,21 @@ def _PageTemplate(self, path, name):
template.__name__ = name
return template
class PageTemplateResourceFactory(ResourceFactory):
"""A factory for Page Template resources"""
factory = _PageTemplate
resource = PageTemplateResource
class FileResourceFactory(ResourceFactory):
"""A factory for File resources"""
factory = File
resource = FileResource
class ImageResourceFactory(ResourceFactory):
"""A factory for Image resources"""
......@@ -117,24 +124,25 @@ class ImageResourceFactory(ResourceFactory):
# we only need this class a context for DirectoryResource
class Directory:
class Directory(object):
def __init__(self, path, name):
self.path = path
self.__name__ = name
class DirectoryResource(Resource,
zope.browserresource.directory.DirectoryResource):
resource_factories = {
'gif': ImageResourceFactory,
'png': ImageResourceFactory,
'jpg': ImageResourceFactory,
'pt': PageTemplateResourceFactory,
'zpt': PageTemplateResourceFactory,
'gif': ImageResourceFactory,
'png': ImageResourceFactory,
'jpg': ImageResourceFactory,
'pt': PageTemplateResourceFactory,
'zpt': PageTemplateResourceFactory,
'html': PageTemplateResourceFactory,
'htm': PageTemplateResourceFactory,
}
'htm': PageTemplateResourceFactory,
}
default_factory = FileResourceFactory
......@@ -164,14 +172,15 @@ class DirectoryResource(Resource,
resource = factory(name, filename)(self.request)
resource.__name__ = name
resource.__parent__ = self
# We need to propagate security so that restrictedTraverse() will
# work
if hasattr(aq_base(self), '__roles__'):
resource.__roles__ = self.__roles__
return resource
class DirectoryResourceFactory(ResourceFactory):
factory = Directory
......
......@@ -26,6 +26,7 @@ from zope.contentprovider.interfaces import IContentProvider
from Products.Five import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
class LegacyAttributes(BrowserView):
"""Make sure that those old aq_* attributes on Five BrowserViews
still work, in particular aq_chain, even though BrowserView may
......@@ -35,6 +36,7 @@ class LegacyAttributes(BrowserView):
def __call__(self):
return repr([obj for obj in self.aq_chain])
class ExplicitLegacyAttributes(Acquisition.Explicit):
"""Make sure that those old aq_* attributes work on browser views
that only inherit from Explicit as well."""
......@@ -42,6 +44,7 @@ class ExplicitLegacyAttributes(Acquisition.Explicit):
def __call__(self):
return repr([obj for obj in self.aq_chain])
class LegacyTemplate(BrowserView):
template = ViewPageTemplateFile('falcon.pt')
......@@ -49,6 +52,7 @@ class LegacyTemplate(BrowserView):
def __call__(self):
return self.template()
class LegacyTemplateTwo(BrowserView):
def __init__(self, context, request):
......@@ -60,21 +64,26 @@ class LegacyTemplateTwo(BrowserView):
def __call__(self):
return self.template()
class Explicit(Acquisition.Explicit):
def render(self):
return 'Explicit'
class ExplicitWithTemplate(Acquisition.Explicit):
template = ViewPageTemplateFile('falcon.pt')
class Implicit(Acquisition.Implicit):
index_html = None # we don't want to acquire this!
def render(self):
return 'Implicit'
class ImplicitWithTemplate(Acquisition.Implicit):
template = ViewPageTemplateFile('falcon.pt')
......@@ -96,6 +105,7 @@ class ExplicitContentProvider(Acquisition.Explicit):
def render(self):
return 'Content provider inheriting from Explicit'
class ExplicitViewlet(Acquisition.Explicit):
def __init__(self, context, request, view, manager):
......@@ -111,6 +121,7 @@ class ExplicitViewlet(Acquisition.Explicit):
def render(self):
return 'Viewlet inheriting from Explicit'
class BrowserViewViewlet(BrowserView):
def __init__(self, context, request, view, manager):
......@@ -139,6 +150,7 @@ class LegacyNamespace(object):
def traverse(self, name, ignored):
return LegacyNamespaceObject(name)
class LegacyNamespaceObject(OFS.SimpleItem.SimpleItem):
def __init__(self, name):
......
......@@ -17,16 +17,19 @@
from zope.interface import Interface, implements
from Products.Five import BrowserView
class IOne(Interface):
"""This is an interface.
"""
class One(object):
'A class'
implements(IOne)
class ViewOne(BrowserView):
'Yet another class'
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 @@
"""
from zope.i18nmessageid import MessageFactory
_ = MessageFactory('fivetest')
from Products.Five import BrowserView
_ = MessageFactory('fivetest')
class I18nView(BrowserView):
this_is_a_message = _(u'This is a message')
......@@ -16,5 +16,6 @@
from zope.publisher.interfaces.browser import IDefaultBrowserLayer
class ITestSkin(IDefaultBrowserLayer):
pass
......@@ -14,6 +14,7 @@
"""Test AbsoluteURL
"""
def test_absoluteurl():
"""This tests the absolute url view (IAbsoluteURL or @@absolute_url),
in particular the breadcrumb functionality.
......@@ -83,6 +84,7 @@ def test_absoluteurl():
>>> tearDown()
"""
def test_suite():
from Testing.ZopeTestCase import ZopeDocTestSuite
return ZopeDocTestSuite()
......@@ -14,6 +14,7 @@
"""Test adding views
"""
def test_suite():
from Testing.ZopeTestCase import ZopeDocFileSuite
return ZopeDocFileSuite('adding.txt',
......
......@@ -14,6 +14,7 @@
"""Unit tests for decode module.
"""
def test_processInputs():
"""
Testing processInputs
......@@ -100,6 +101,7 @@ def test_processInputs():
"""
def test_suite():
from doctest import DocTestSuite
return DocTestSuite()
......@@ -14,6 +14,7 @@
"""Test Default View functionality
"""
def test_default_view():
"""
Test default view functionality
......@@ -176,6 +177,7 @@ def test_default_method_args_marshalling():
>>> cleanUp()
"""
def test_suite():
from Testing.ZopeTestCase import FunctionalDocTestSuite
return FunctionalDocTestSuite()
......@@ -14,12 +14,13 @@
"""Unit tests for the i18n framework
"""
def test_zpt_i18n():
"""
Test i18n functionality in ZPTs
>>> configure_zcml = '''
... <configure
... <configure
... xmlns="http://namespaces.zope.org/zope"
... xmlns:browser="http://namespaces.zope.org/browser"
... xmlns:i18n="http://namespaces.zope.org/i18n">
......@@ -81,6 +82,7 @@ def test_zpt_i18n():
>>> tearDown()
"""
def test_suite():
from Testing.ZopeTestCase import FunctionalDocTestSuite
from doctest import ELLIPSIS
......
......@@ -14,6 +14,7 @@
"""Test browser menus
"""
def test_menu():
"""
Test menus
......@@ -39,7 +40,7 @@ def test_menu():
>>> request = TestRequest()
>>> menu = getMenu('testmenu', self.folder, request)
It should have
It should have
>>> len(menu)
4
......@@ -149,7 +150,7 @@ def test_menu():
'description': u'This is a test menu item',
'extra': None,
'icon': None,
'selected': u'',
'selected': u'',
'submenu': None,
'title': u'Test Menu Item 2'}
......@@ -169,6 +170,7 @@ def test_menu():
>>> tearDown()
"""
def test_suite():
from Testing.ZopeTestCase import ZopeDocTestSuite
return ZopeDocTestSuite()
import unittest
class ViewMixinForTemplatesTests(unittest.TestCase):
def _getTargetClass(self):
......@@ -41,7 +42,7 @@ class ViewMixinForTemplatesTests(unittest.TestCase):
index.macros = {}
index.macros['aaa'] = aaa = object()
self.assertTrue(view['aaa'] is aaa)
def test__getitem__gives_shortcut_to_index_macros(self):
view = self._makeOne()
view.index = index = DummyTemplate()
......@@ -77,18 +78,15 @@ class ViewMixinForTemplatesTests(unittest.TestCase):
self.assertEqual(index._called_with, (('abc',), {'foo': 'bar'}))
class DummyContext:
class DummyContext(object):
pass
class DummyRequest:
class DummyRequest(object):
pass
class DummyTemplate:
def __call__(self, *args, **kw):
self._called_with = (args, kw)
return self
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(ViewMixinForTemplatesTests),
))
......@@ -15,6 +15,7 @@
"""
import unittest
def test_view_with_unwrapped_context():
"""
It may be desirable when writing tests for views themselves to
......@@ -63,6 +64,7 @@ def test_view_with_unwrapped_context():
>>> tearDown()
"""
def test_suite():
from Testing.ZopeTestCase import FunctionalDocFileSuite
from Testing.ZopeTestCase import ZopeDocFileSuite
......@@ -74,4 +76,4 @@ def test_suite():
package='Products.Five.browser.tests'),
FunctionalDocFileSuite('aqlegacy_ftest.txt',
package='Products.Five.browser.tests'),
))
))
......@@ -37,8 +37,6 @@ class ViewPageTemplateFileTests(unittest.TestCase):
def test_pt_getEngine(self):
from zope.tales.expressions import DeferExpr
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.contentprovider.tales import TALESProviderExpression
from Products.PageTemplates.DeferExpr import LazyExpr
......@@ -85,8 +83,6 @@ class ViewPageTemplateFileTests(unittest.TestCase):
self.assertEqual(namespace['user'].getId(), 'a_user')
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
newSecurityManager(None, DummyUser('a_user'))
context = DummyContext()
......@@ -99,8 +95,6 @@ class ViewPageTemplateFileTests(unittest.TestCase):
self.assertTrue(namespace['root'] is root)
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
newSecurityManager(None, DummyUser('a_user'))
context = DummyContext()
......@@ -112,8 +106,6 @@ class ViewPageTemplateFileTests(unittest.TestCase):
self.assertFalse('foo' in namespace['options'])
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
newSecurityManager(None, DummyUser('a_user'))
context = DummyContext()
......@@ -124,8 +116,6 @@ class ViewPageTemplateFileTests(unittest.TestCase):
self.assertEqual(namespace['args'], ('bar', 'baz'))
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
newSecurityManager(None, DummyUser('a_user'))
context = DummyContext()
......@@ -149,20 +139,22 @@ class ViewPageTemplateFileTests(unittest.TestCase):
context = DummyContext()
request = DummyRequest()
response = request.response = DummyResponse(
{'Content-Type': 'text/xhtml'})
{'Content-Type': 'text/xhtml'})
view = self._makeView(context, request)
vptf = self._makeOne('templates/dirpage1.pt')
body = vptf(view)
vptf(view)
self.assertEqual(response._headers['Content-Type'], 'text/xhtml')
def test___get___(self):
from Products.Five.browser.pagetemplatefile import BoundPageTemplate
template = self._makeOne('templates/dirpage1.pt')
class Foo:
class Foo(object):
def __init__(self, context, request):
self.context = context
self.request = request
bar = template
context = DummyContext()
request = DummyRequest()
foo = Foo(context, request)
......@@ -171,6 +163,7 @@ class ViewPageTemplateFileTests(unittest.TestCase):
self.assertTrue(bound.im_func is template)
self.assertTrue(bound.im_self is foo)
class ViewMapperTests(unittest.TestCase):
def setUp(self):
......@@ -200,14 +193,17 @@ class ViewMapperTests(unittest.TestCase):
def test___getitem___hit(self):
from zope.interface import Interface
from zope.component import provideAdapter
def _adapt(context, request):
return self
provideAdapter(_adapt, (None, None), Interface, name='test')
mapper = self._makeOne()
self.assertTrue(mapper['test'] is self)
_marker = object()
class BoundPageTemplateTests(unittest.TestCase):
def _getTargetClass(self):
......@@ -269,13 +265,16 @@ DIRPAGE1 = """\
</html>
"""
class DummyContext:
class DummyContext(object):
pass
class DummyRequest:
class DummyRequest(object):
debug = object()
class DummyResponse:
class DummyResponse(object):
def __init__(self, headers=None):
if headers is None:
headers = {}
......@@ -287,30 +286,31 @@ class DummyResponse:
def setHeader(self, name, value):
self._headers[name] = value
class DummyTemplate:
class DummyTemplate(object):
filename = 'dummy.pt'
def __init__(self, macros=None):
if macros is None:
macros = {}
self.macros = macros
def __call__(self, im_self, *args, **kw):
self._called_with = (im_self, args, kw)
return '<h1>Dummy</h1>'
class DummyView:
class DummyView(object):
def __init__(self, context, request):
self.context = context
self.request = request
class DummyUser:
class DummyUser(object):
def __init__(self, name):
self._name = name
def getId(self):
return self._name
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(ViewPageTemplateFileTests),
unittest.makeSuite(ViewMapperTests),
unittest.makeSuite(BoundPageTemplateTests),
))
......@@ -14,6 +14,7 @@
"""Test browser pages
"""
def test_suite():
from Testing.ZopeTestCase import FunctionalDocFileSuite
return FunctionalDocFileSuite('provider.txt',
......
......@@ -14,6 +14,7 @@
"""Test default view recursion
"""
def test_recursion():
"""
Test recursion
......@@ -59,6 +60,7 @@ def test_recursion():
>>> cleanUp()
"""
def test_suite():
from Testing.ZopeTestCase import ZopeDocTestSuite
return ZopeDocTestSuite()
......@@ -15,12 +15,13 @@
"""
import unittest
def test_suite():
from Testing.ZopeTestCase import FunctionalDocFileSuite
from Testing.ZopeTestCase import ZopeDocFileSuite
return unittest.TestSuite((
ZopeDocFileSuite('resource.txt',
package='Products.Five.browser.tests'),
FunctionalDocFileSuite('resource_ftest.txt',
package='Products.Five.browser.tests'),
))
ZopeDocFileSuite('resource.txt',
package='Products.Five.browser.tests'),
FunctionalDocFileSuite('resource_ftest.txt',
package='Products.Five.browser.tests'),
))
......@@ -18,7 +18,7 @@ def checkRestricted(folder, psbody):
addPythonScript(folder, 'ps', body=psbody)
try:
folder.ps()
except Unauthorized, e:
except Unauthorized as e:
raise AssertionError(e)
......@@ -94,7 +94,7 @@ def test_resource_restricted_code():
>>> self.folder.restrictedTraverse('++resource++fivetest_resources/resource.txt') is not None
True
>>> self.folder.restrictedTraverse('++resource++fivetest_resources/resource_subdir/resource.txt') is not None
True
......@@ -104,6 +104,7 @@ def test_resource_restricted_code():
>>> tearDown()
"""
def test_view_restricted_code():
"""
Let's register a quite large amount of test pages:
......@@ -128,7 +129,7 @@ def test_view_restricted_code():
>>> protected_view_names = [
... 'eagle.txt', 'falcon.html', 'owl.html', 'flamingo.html',
... 'condor.html', 'permission_view']
>>>
>>> public_view_names = [
... 'public_attribute_page',
... 'public_template_page',
......@@ -181,7 +182,7 @@ def test_view_restricted_code():
def test_suite():
suite = unittest.TestSuite()
try:
import Products.PythonScripts
import Products.PythonScripts # NOQA
except ImportError:
pass
else:
......
......@@ -14,6 +14,7 @@
"""Test browser pages
"""
def test_suite():
from Testing.ZopeTestCase import FunctionalDocFileSuite
return FunctionalDocFileSuite('skin.txt',
......
......@@ -14,6 +14,7 @@
"""Test Five-traversable classes
"""
class SimpleClass(object):
"""Class with no __bobo_traverse__."""
......@@ -48,7 +49,7 @@ def test_traversable():
... xmlns:meta="http://namespaces.zope.org/meta"
... xmlns:browser="http://namespaces.zope.org/browser"
... xmlns:five="http://namespaces.zope.org/five">
...
...
... <!-- make the zope2.Public permission work -->
... <meta:redefinePermission from="zope2.Public" to="zope.Public" />
...
......@@ -129,7 +130,7 @@ def test_traversable():
Five's traversable monkeypatches the __bobo_traverse__ method to do view
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
__bobo_traverse__ method itself does it (i.e. the __bobo_traverse__ is the
only element used for traversal lookup). Let's demonstrate:
......@@ -179,6 +180,7 @@ def test_traversable():
False
"""
def test_view_doesnt_shadow_attribute():
"""
Test that views don't shadow attributes, e.g. items in a folder.
......@@ -265,7 +267,7 @@ def test_view_doesnt_shadow_attribute():
However, acquired attributes *should* be shadowed. See discussion on
http://codespeak.net/pipermail/z3-five/2006q2/001474.html
>>> manage_addIndexSimpleContent(self.folder, 'mouse', 'Mouse')
>>> print http(r'''
... GET /test_folder_1_/ftf/mouse HTTP/1.1
......@@ -273,13 +275,14 @@ def test_view_doesnt_shadow_attribute():
HTTP/1.1 200 OK
...
The mouse has been eaten by the eagle
Clean up:
>>> from zope.component.testing import tearDown
>>> tearDown()
"""
def test_suite():
from Testing.ZopeTestCase import FunctionalDocTestSuite
return FunctionalDocTestSuite()
......@@ -7,7 +7,7 @@ def test_check_permission():
work.
>>> configure_zcml = '''
... <configure
... <configure
... xmlns="http://namespaces.zope.org/zope"
... xmlns:browser="http://namespaces.zope.org/browser">
... <securityPolicy
......@@ -53,6 +53,7 @@ def test_check_permission():
"""
def test_allowed_interface():
"""This test demonstrates that allowed_interface security declarations work
as expected.
......@@ -143,6 +144,7 @@ def test_allowed_interface():
>>> tearDown()
"""
def test_suite():
from Testing.ZopeTestCase import FunctionalDocTestSuite
from doctest import ELLIPSIS
......
from zope.publisher.browser import BrowserView
from zope.security.management import checkPermission
class Zope3SecurityView(BrowserView):
def __call__(self, permission):
......
......@@ -32,6 +32,7 @@ from ZPublisher.BeforeTraverse import unregisterBeforeTraverse
from zope.component.hooks import setHooks
setHooks()
def findSite(obj, iface=ISite):
"""Find a site by walking up the object hierarchy, supporting both
the ``ILocation`` API and Zope 2 Acquisition."""
......@@ -39,6 +40,7 @@ def findSite(obj, iface=ISite):
obj = aq_parent(aq_inner(obj))
return obj
@zope.component.adapter(zope.interface.Interface)
@zope.interface.implementer(IComponentLookup)
def siteManagerAdapter(ob):
......@@ -51,6 +53,7 @@ def siteManagerAdapter(ob):
return zope.component.getGlobalSiteManager()
return site.getSiteManager()
class LocalSiteHook(ExtensionClass.Base):
def __call__(self, container, request):
......@@ -58,6 +61,7 @@ class LocalSiteHook(ExtensionClass.Base):
HOOK_NAME = '__local_site_hook__'
def enableSite(obj, iface=ISite):
"""Install __before_traverse__ hook for Local Site
"""
......@@ -73,6 +77,7 @@ def enableSite(obj, iface=ISite):
zope.interface.alsoProvides(obj, iface)
def disableSite(obj, iface=ISite):
"""Remove __before_traverse__ hook for Local Site
"""
......
......@@ -27,9 +27,9 @@ class ObjectManagerSiteView(BrowserView):
def update(self):
form = self.request.form
if form.has_key('MAKESITE'):
if 'MAKESITE' in form:
self.makeSite()
elif form.has_key('UNMAKESITE'):
elif 'UNMAKESITE' in form:
self.unmakeSite()
def isSite(self):
......@@ -41,7 +41,7 @@ class ObjectManagerSiteView(BrowserView):
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
components = PersistentComponents()
components.__bases__ = (base,)
......
......@@ -19,5 +19,4 @@ from OFS.interfaces import IObjectManager
class IObjectManagerSite(IObjectManager, ISite):
"""Object manager that is also a site."""
......@@ -24,4 +24,4 @@ def test_suite():
DocFileSuite('component.txt', package="Products.Five.component"),
FunctionalDocFileSuite('makesite.txt',
package="Products.Five.component"),
])
])
......@@ -21,6 +21,7 @@ from Products.Five import fivemethod, isFiveMethod
# holds classes that were monkeyed with; for clean up
_monkied = []
@fivemethod
def get_size(self):
size = ISized(self, None)
......@@ -32,6 +33,7 @@ def get_size(self):
if method is not None:
return self.__five_original_get_size()
def classSizable(class_):
"""Monkey the class to be sizable through Five"""
# tuck away the original method if necessary
......@@ -41,14 +43,15 @@ def classSizable(class_):
# remember class for clean up
_monkied.append(class_)
def sizable(_context, class_):
_context.action(
discriminator = ('five:sizable', class_),
callable = classSizable,
discriminator=('five:sizable', class_),
callable=classSizable,
args=(class_,)
)
)
# clean up code
def killMonkey(class_, name, fallback, attr=None):
"""Die monkey, die!"""
method = getattr(class_, name, None)
......@@ -70,14 +73,17 @@ def killMonkey(class_, name, fallback, attr=None):
except (AttributeError, KeyError):
pass
def unsizable(class_):
"""Restore class's initial state with respect to being sizable"""
killMonkey(class_, 'get_size', '__five_original_get_size')
def cleanUp():
for class_ in _monkied:
unsizable(class_)
from zope.testing.cleanup import addCleanUp
from zope.testing.cleanup import addCleanUp # NOQA
addCleanUp(cleanUp)
del addCleanUp
......@@ -18,9 +18,8 @@ import zope.interface
import zope.component
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:
class Macros(object):
zope.interface.implements(zope.interface.common.mapping.IItemMapping)
macro_pages = ()
......@@ -28,24 +27,27 @@ class Macros:
'view': 'page',
'dialog': 'page',
'addingdialog': 'page'
}
}
def __getitem__(self, key):
key = self.aliases.get(key, key)
context = self.context
request = self.request
for name in self.macro_pages:
page = zope.component.getMultiAdapter((context, request), name=name)
page = zope.component.getMultiAdapter(
(context, request), name=name)
try:
v = page[key]
except KeyError:
pass
else:
return v
raise KeyError, key
raise KeyError(key)
class StandardMacros(BrowserView, Macros):
macro_pages = ('five_template',
'widget_macros',
'form_macros',)
macro_pages = (
'five_template',
'widget_macros',
'form_macros',
)
......@@ -16,8 +16,11 @@
from Products.Five import StandardMacros as BaseMacros
class StandardMacros(BaseMacros):
macro_pages = ('bird_macros', 'dog_macros')
aliases = {'flying':'birdmacro',
'walking':'dogmacro'}
aliases = {
'flying': 'birdmacro',
'walking': 'dogmacro',
}
......@@ -14,6 +14,7 @@
"""Test standard macros
"""
def test_standard_macros():
"""Test standard macros
......@@ -27,7 +28,7 @@ def test_standard_macros():
>>> import Products.Five.skin.tests
>>> from Zope2.App import zcml
>>> 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,
when looking up a non-existing macro, we get a KeyError:
......@@ -71,6 +72,7 @@ def test_standard_macros():
>>> tearDown()
"""
def test_suite():
from Testing.ZopeTestCase import 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 @@
from zope.interface import implements, Interface
from zope.component import adapts
class IAdaptable(Interface):
"""This is a Zope interface.
"""
......@@ -24,6 +25,7 @@ class IAdaptable(Interface):
"""This method will be adapted
"""
class IAdapted(Interface):
"""The interface we adapt to.
"""
......@@ -32,22 +34,26 @@ class IAdapted(Interface):
"""A method to adapt.
"""
class IOrigin(Interface):
"""Something we'll adapt"""
class IDestination(Interface):
"""The result of an adaption"""
def method():
"""Do something"""
class Adaptable:
class Adaptable(object):
implements(IAdaptable)
def method(self):
return "The method"
class Adapter:
class Adapter(object):
implements(IAdapted)
adapts(IAdaptable)
......@@ -57,10 +63,12 @@ class Adapter:
def adaptedMethod(self):
return "Adapted: %s" % self.context.method()
class Origin:
class Origin(object):
implements(IOrigin)
class OriginalAdapter:
class OriginalAdapter(object):
implements(IDestination)
def __init__(self, context):
......@@ -69,7 +77,8 @@ class OriginalAdapter:
def method(self):
return "Original"
class OverrideAdapter:
class OverrideAdapter(object):
implements(IDestination)
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 @@
from zope.interface import Interface
class One(object):
'A class'
class Two(object):
'Another class'
class IOne(Interface):
"""This is a Zope interface.
"""
class ITwo(Interface):
"""This is another Zope interface.
"""
......@@ -18,27 +18,28 @@ from zope.interface import Interface
from zope.configuration.fields import GlobalObject
from zope.schema import TextLine
class IParrotDirective(Interface):
"""State that a class implements something.
"""
class_ = GlobalObject(
title=u"Class",
required=True
)
required=True,
)
name = TextLine(
title=u"Name",
description=u"The parrots name.",
required=True
)
required=True,
)
def parrot(_context, class_, name):
parrot = class_()
parrot.pineForFjords()
class NorwegianBlue(object):
def pineForFjords(self):
return "This parrot is no more!"
......@@ -14,6 +14,7 @@
"""Test the basic ZCML directives
"""
def test_directives():
"""
Test ZCML directives
......
......@@ -16,6 +16,7 @@
from zope.component.testing import setUp, tearDown
def test_directive():
"""
Test the i18n directive. First, we need to register the ZCML
......
......@@ -17,6 +17,7 @@
from zope.interface import implements
from zope.size.interfaces import ISized
class SimpleContentSize(object):
"""Size for ``SimpleContent`` objects."""
implements(ISized)
......@@ -30,6 +31,7 @@ class SimpleContentSize(object):
def sizeForDisplay(self):
return "What is the meaning of life?"
class FancyContentSize(object):
"""Size for ``SimpleContent`` objects."""
implements(ISized)
......@@ -43,6 +45,7 @@ class FancyContentSize(object):
def sizeForDisplay(self):
return "That's not the meaning of life!"
def test_size():
"""
Test size adapters
......@@ -94,6 +97,7 @@ def test_size():
>>> tearDown()
"""
def test_suite():
from Testing.ZopeTestCase import ZopeDocTestSuite
return ZopeDocTestSuite()
......@@ -14,7 +14,9 @@
"""Test helpers
"""
from Products.Five.tests.testing.folder import FiveTraversableFolder
from Products.Five.tests.testing.folder import manage_addFiveTraversableFolder
from Products.Five.tests.testing.folder import manage_addNoVerifyPasteFolder
from Products.Five.tests.testing.folder import NoVerifyPasteFolder
from Products.Five.tests.testing.folder import ( # NOQA
FiveTraversableFolder,
manage_addFiveTraversableFolder,
manage_addNoVerifyPasteFolder,
NoVerifyPasteFolder,
)
......@@ -22,9 +22,11 @@ from OFS.SimpleItem import SimpleItem
from zope.interface import implements
from zope.interface import Interface
class IFancyContent(Interface):
pass
class FancyAttribute(Explicit):
"""Doc test fanatics"""
......@@ -40,6 +42,7 @@ class FancyAttribute(Explicit):
InitializeClass(FancyAttribute)
class FancyContent(SimpleItem):
"""A class that already comes with its own __bobo_traverse__ handler.
Quite fancy indeed.
......@@ -65,13 +68,14 @@ class FancyContent(SimpleItem):
InitializeClass(FancyContent)
# A copy of the above class used to demonstrate some baseline behavior
class NonTraversableFancyContent(SimpleItem):
"""A class that already comes with its own __bobo_traverse__ handler.
Quite fancy indeed.
It also comes with its own get_size method.
"""
# A copy of the above class used to demonstrate some baseline behavior.
implements(IFancyContent)
meta_type = "Fancy Content"
......@@ -91,11 +95,13 @@ class NonTraversableFancyContent(SimpleItem):
InitializeClass(NonTraversableFancyContent)
def manage_addFancyContent(self, id, REQUEST=None):
"""Add the fancy fancy content."""
id = self._setObject(id, FancyContent(id))
return ''
def manage_addNonTraversableFancyContent(self, id, REQUEST=None):
"""Add the fancy fancy content."""
id = self._setObject(id, NonTraversableFancyContent(id))
......
......@@ -18,6 +18,7 @@ from OFS.Folder import Folder
from OFS.interfaces import IFolder
from zope.interface import implements
class NoVerifyPasteFolder(Folder):
"""Folder that does not perform paste verification.
Used by test_events
......@@ -25,17 +26,20 @@ class NoVerifyPasteFolder(Folder):
def _verifyObjectPaste(self, object, validate_src=1):
pass
def manage_addNoVerifyPasteFolder(container, id, title=''):
container._setObject(id, NoVerifyPasteFolder())
folder = container[id]
folder.id = id
folder.title = title
class FiveTraversableFolder(Folder):
"""Folder that is five-traversable
"""
implements(IFolder)
def manage_addFiveTraversableFolder(container, id, title=''):
container._setObject(id, FiveTraversableFolder())
folder = container[id]
......
def somemethod(self):
print "Executed somemethod"
print("Executed somemethod")
def initialize(context):
print "pythonproduct2 initialized"
print("pythonproduct2 initialized")
......@@ -21,15 +21,19 @@ from OFS.SimpleItem import SimpleItem
from zope.interface import implements
from zope.interface import Interface
class ISimpleContent(Interface):
pass
class ICallableSimpleContent(ISimpleContent):
pass
class IIndexSimpleContent(ISimpleContent):
pass
class SimpleContent(SimpleItem):
implements(ISimpleContent)
......@@ -52,6 +56,7 @@ class SimpleContent(SimpleItem):
InitializeClass(SimpleContent)
class CallableSimpleContent(SimpleItem):
"""A Viewable piece of content"""
implements(ICallableSimpleContent)
......@@ -64,6 +69,7 @@ class CallableSimpleContent(SimpleItem):
InitializeClass(CallableSimpleContent)
class IndexSimpleContent(SimpleItem):
"""A Viewable piece of content"""
implements(IIndexSimpleContent)
......@@ -76,14 +82,17 @@ class IndexSimpleContent(SimpleItem):
InitializeClass(IndexSimpleContent)
def manage_addSimpleContent(self, id, title, REQUEST=None):
"""Add the simple content."""
self._setObject(id, SimpleContent(id, title))
def manage_addCallableSimpleContent(self, id, title, REQUEST=None):
"""Add the viewable simple content."""
self._setObject(id, CallableSimpleContent(id, title))
def manage_addIndexSimpleContent(self, id, title, REQUEST=None):
"""Add the viewable simple content."""
self._setObject(id, IndexSimpleContent(id, title))
......@@ -17,8 +17,7 @@
from Products.Five.utilities.interfaces import IMarkerInterfaces
class EditView:
class EditView(object):
"""Marker interface edit view.
"""
......@@ -36,8 +35,9 @@ class EditView:
return self.index()
def _getLinkToInterfaceDetailsView(self, interfaceName):
return (self.context_url +
'/views-details.html?iface=%s&type=zope.publisher.interfaces.browser.IBrowserRequest' % interfaceName)
return (self.context_url + (
'/views-details.html?iface=%s&type=zope.publisher.'
'interfaces.browser.IBrowserRequest' % interfaceName))
def _getNameLinkDicts(self, interfaceNames):
return [dict(name=name,
......
......@@ -14,6 +14,7 @@
"""Unit tests for marker interface views.
"""
def test_editview():
"""
Set everything up:
......@@ -84,6 +85,7 @@ def test_editview():
>>> tearDown()
"""
def test_suite():
from Testing.ZopeTestCase import ZopeDocTestSuite
return ZopeDocTestSuite()
......@@ -26,6 +26,7 @@ from zope.component.interface import searchInterface
from interfaces import IMarkerInterfaces
def interfaceStringCheck(f):
def wrapper(ob, interface):
if isinstance(interface, str):
......@@ -33,11 +34,13 @@ def interfaceStringCheck(f):
return f(ob, interface)
return wrapper
def mark(ob, interface):
directlyProvides(ob, directlyProvidedBy(ob), interface)
def erase(ob, interface):
directlyProvides(ob, directlyProvidedBy(ob)-interface)
directlyProvides(ob, directlyProvidedBy(ob) - interface)
mark = interfaceStringCheck(mark)
erase = interfaceStringCheck(erase)
......@@ -74,8 +77,8 @@ class MarkerInterfacesAdapter(object):
todo.append(base)
markers = self._getDirectMarkersOf(interface)
for interface in markers:
if (interface not in results
and not interface.providedBy(self.context)):
if (interface not in results and
not interface.providedBy(self.context)):
results.append(interface)
todo += markers
return tuple(results)
......
# A package for viewlet support
\ No newline at end of file
......@@ -369,7 +369,7 @@ specified attribute:
Traceback (most recent call last):
...
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
......
......@@ -23,6 +23,7 @@ from zope.viewlet.manager import ViewletManagerBase as origManagerBase
from Products.Five.browser.pagetemplatefile import ZopeTwoPageTemplateFile
class ViewletManagerBase(origManagerBase):
"""A base class for Viewlet managers to work in Zope2"""
......@@ -38,14 +39,14 @@ class ViewletManagerBase(origManagerBase):
# If the viewlet was not found, then raise a lookup error
if viewlet is None:
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
# unauthorized error
if not guarded_hasattr(viewlet, 'render'):
raise zope.security.interfaces.Unauthorized(
'You are not authorized to access the provider '
'called `%s`.' %name)
'called `%s`.' % name)
# Return the viewlet.
return viewlet
......@@ -73,7 +74,12 @@ class ViewletManagerBase(origManagerBase):
# By default, use the standard Python way of doing sorting. Unwrap the
# objects first so that they are sorted as expected. This is dumb
# 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=()):
attrDict = {'__name__': name}
......
......@@ -31,11 +31,12 @@ from AccessControl.security import protectName
from Products.Five.viewlet import manager
from Products.Five.viewlet import viewlet
def viewletManagerDirective(
_context, name, permission,
for_=Interface, layer=IDefaultBrowserLayer, view=IBrowserView,
provides=interfaces.IViewletManager, class_=None, template=None,
allowed_interface=None, allowed_attributes=None):
_context, name, permission,
for_=Interface, layer=IDefaultBrowserLayer, view=IBrowserView,
provides=interfaces.IViewletManager, class_=None, template=None,
allowed_interface=None, allowed_attributes=None):
# If class is not given we use the basic viewlet manager.
if class_ is None:
......@@ -69,36 +70,37 @@ def viewletManagerDirective(
# register a viewlet manager
_context.action(
discriminator = ('viewletManager', for_, layer, view, name),
callable = zcml.handler,
args = ('registerAdapter',
new_class, (for_, layer, view), provides, name,
_context.info),)
discriminator=('viewletManager', for_, layer, view, name),
callable=zcml.handler,
args=('registerAdapter',
new_class, (for_, layer, view), provides, name,
_context.info),
)
_context.action(
discriminator = ('five:protectClass', new_class),
callable = protectClass,
args = (new_class, permission)
)
discriminator=('five:protectClass', new_class),
callable=protectClass,
args=(new_class, permission),
)
if allowed_attributes:
for attr in allowed_attributes:
_context.action(
discriminator = ('five:protectName', new_class, attr),
callable = protectName,
args = (new_class, attr, permission)
)
discriminator=('five:protectName', new_class, attr),
callable=protectName,
args=(new_class, attr, permission),
)
_context.action(
discriminator = ('five:initialize:class', new_class),
callable = InitializeClass,
args = (new_class,)
)
discriminator=('five:initialize:class', new_class),
callable=InitializeClass,
args=(new_class, ),
)
def viewletDirective(
_context, name, permission,
for_=Interface, layer=IDefaultBrowserLayer, view=IBrowserView,
manager=interfaces.IViewletManager, class_=None, template=None,
attribute='render', allowed_interface=None, allowed_attributes=None,
**kwargs):
_context, name, permission,
for_=Interface, layer=IDefaultBrowserLayer, view=IBrowserView,
manager=interfaces.IViewletManager, class_=None, template=None,
attribute='render', allowed_interface=None,
allowed_attributes=None, **kwargs):
# Either the class or template must be specified.
if not (class_ or template):
......@@ -135,8 +137,8 @@ def viewletDirective(
if attribute != 'render':
if not hasattr(class_, attribute):
raise ConfigurationError(
"The provided class doesn't have the specified attribute "
)
"The provided class doesn't have the specified attribute."
)
if template:
# Create a new class for the viewlet template and class.
new_class = viewlet.SimpleViewletClass(
......@@ -165,26 +167,26 @@ def viewletDirective(
# register viewlet
_context.action(
discriminator = ('viewlet', for_, layer, view, manager, name),
callable = zcml.handler,
args = ('registerAdapter',
new_class, (for_, layer, view, manager),
interfaces.IViewlet, name, _context.info),)
discriminator=('viewlet', for_, layer, view, manager, name),
callable=zcml.handler,
args=('registerAdapter',
new_class, (for_, layer, view, manager),
interfaces.IViewlet, name, _context.info),
)
_context.action(
discriminator = ('five:protectClass', new_class),
callable = protectClass,
args = (new_class, permission)
)
discriminator=('five:protectClass', new_class),
callable=protectClass,
args=(new_class, permission)
)
if allowed_attributes:
for attr in allowed_attributes:
_context.action(
discriminator = ('five:protectName', new_class, attr),
callable = protectName,
args = (new_class, attr, permission)
)
discriminator=('five:protectName', new_class, attr),
callable=protectName,
args=(new_class, attr, permission)
)
_context.action(
discriminator = ('five:initialize:class', new_class),
callable = InitializeClass,
args = (new_class,)
)
discriminator=('five:initialize:class', new_class),
callable=InitializeClass,
args=(new_class,)
)
......@@ -21,54 +21,64 @@ from zope.interface import implements
from zope.viewlet import interfaces
from OFS.SimpleItem import SimpleItem
class Content(SimpleItem):
implements(Interface)
class UnitTestSecurityPolicy:
"""
Stub out the existing security policy for unit testing purposes.
"""
#
# Standard SecurityPolicy interface
#
def validate( self
, accessed=None
, container=None
, name=None
, value=None
, context=None
, roles=None
, *args
, **kw):
# Standard SecurityPolicy interface
def validate(self,
accessed=None,
container=None,
name=None,
value=None,
context=None,
roles=None,
*args, **kw):
return 1
def checkPermission( self, permission, object, context) :
def checkPermission(self, permission, object, context):
return 1
class ILeftColumn(interfaces.IViewletManager):
"""Left column of my page."""
class INewColumn(interfaces.IViewletManager):
"""Left column of my page."""
class WeightBasedSorting(object):
def sort(self, viewlets):
return sorted(viewlets,
lambda x, y: cmp(x[1].weight, y[1].weight))
def _key(info):
return getattr(info[1], 'weight', 0)
return sorted(viewlets, key=_key)
class Weather(object):
weight = 0
class Stock(object):
weight = 0
def getStockTicker(self):
return u'SRC $5.19'
class Sport(object):
weight = 0
def __call__(self):
return u'Red Sox vs. White Sox'
class DynamicTempBox(object):
weight = 0
city = {'name': 'Los Angeles, CA', 'temp': 78}
......@@ -78,4 +88,4 @@ def test_suite():
return unittest.TestSuite([
FunctionalDocFileSuite('README.txt'),
FunctionalDocFileSuite('directives.txt'),
])
])
......@@ -19,19 +19,22 @@ import zope.viewlet.viewlet
from Products.Five.bbb import AcquisitionBBB
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
class ViewletBase(zope.viewlet.viewlet.ViewletBase, AcquisitionBBB):
pass
class SimpleAttributeViewlet(zope.viewlet.viewlet.SimpleAttributeViewlet,
AcquisitionBBB):
pass
class simple(zope.viewlet.viewlet.simple):
# We need to ensure that the proper __init__ is called.
__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
information.
"""
......@@ -39,8 +42,8 @@ def SimpleViewletClass(template, bases=(), attributes=None,
# Create the base class hierarchy
bases += (simple, ViewletBase)
attrs = {'index' : ViewPageTemplateFile(template),
'__name__' : name}
attrs = {'index': ViewPageTemplateFile(template),
'__name__': name}
if attributes:
attrs.update(attributes)
......@@ -53,14 +56,14 @@ def SimpleViewletClass(template, bases=(), attributes=None,
class ResourceViewletBase(zope.viewlet.viewlet.ResourceViewletBase):
pass
def JavaScriptViewlet(path):
"""Create a viewlet that can simply insert a javascript link."""
src = os.path.join(os.path.dirname(__file__), 'javascript_viewlet.pt')
klass = type('JavaScriptViewlet',
(ResourceViewletBase, ViewletBase),
{'index': ViewPageTemplateFile(src),
'_path': path})
{'index': ViewPageTemplateFile(src), '_path': path})
return klass
......@@ -68,15 +71,16 @@ def JavaScriptViewlet(path):
class CSSResourceViewletBase(zope.viewlet.viewlet.CSSResourceViewletBase):
pass
def CSSViewlet(path, media="all", rel="stylesheet"):
"""Create a viewlet that can simply insert a javascript link."""
src = os.path.join(os.path.dirname(__file__), 'css_viewlet.pt')
klass = type('CSSViewlet',
(CSSResourceViewletBase, ViewletBase),
{'index': ViewPageTemplateFile(src),
'_path': path,
'_media':media,
'_rel':rel})
{'index': ViewPageTemplateFile(src),
'_path': path,
'_media': media,
'_rel': rel})
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