tested django-newsletter

This commit is contained in:
Esther Kleinhenz
2018-10-26 15:21:17 +02:00
parent 7ed667d043
commit 811b7c5453
2352 changed files with 448169 additions and 1 deletions
@@ -0,0 +1,18 @@
##############################################################################
#
# Copyright (c) 2004 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.
#
##############################################################################
"""Annotation (meta data) support
"""
from zope.annotation.interfaces import IAttributeAnnotatable
from zope.annotation.interfaces import IAnnotations
from zope.annotation.factory import factory
@@ -0,0 +1,102 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Attribute Annotations implementation"""
import logging
try:
from collections.abc import MutableMapping as DictMixin
except ImportError:
# Python 2
from collections import MutableMapping as DictMixin
try:
from BTrees.OOBTree import OOBTree as _STORAGE
except ImportError: # pragma: no cover
logging.getLogger(__name__).warning(
'BTrees not available: falling back to dict for attribute storage')
_STORAGE = dict
from zope import component, interface
from zope.annotation import interfaces
_EMPTY_STORAGE = _STORAGE()
@interface.implementer(interfaces.IAnnotations)
@component.adapter(interfaces.IAttributeAnnotatable)
class AttributeAnnotations(DictMixin):
"""Store annotations on an object
Store annotations in the `__annotations__` attribute on a
`IAttributeAnnotatable` object.
"""
# Yes, there's a lot of repetition of the `getattr` call,
# but that turns out to be the most efficient for the ways
# instances are typically used without sacrificing any semantics.
# See https://github.com/zopefoundation/zope.annotation/issues/8
# for a discussion of alternatives (which included functools.partial,
# a closure, capturing the annotations in __init__, and versions
# with getattr and exceptions).
def __init__(self, obj, context=None):
self.obj = obj
@property
def __parent__(self):
return self.obj
def __bool__(self):
return bool(getattr(self.obj, '__annotations__', 0))
__nonzero__ = __bool__
def get(self, key, default=None):
"""See zope.annotation.interfaces.IAnnotations"""
annotations = getattr(self.obj, '__annotations__', _EMPTY_STORAGE)
return annotations.get(key, default)
def __getitem__(self, key):
annotations = getattr(self.obj, '__annotations__', _EMPTY_STORAGE)
return annotations[key]
def keys(self):
annotations = getattr(self.obj, '__annotations__', _EMPTY_STORAGE)
return annotations.keys()
def __iter__(self):
annotations = getattr(self.obj, '__annotations__', _EMPTY_STORAGE)
return iter(annotations)
def __len__(self):
annotations = getattr(self.obj, '__annotations__', _EMPTY_STORAGE)
return len(annotations)
def __setitem__(self, key, value):
"""See zope.annotation.interfaces.IAnnotations"""
try:
annotations = self.obj.__annotations__
except AttributeError:
annotations = self.obj.__annotations__ = _STORAGE()
annotations[key] = value
def __delitem__(self, key):
"""See zope.app.interfaces.annotation.IAnnotations"""
try:
annotation = self.obj.__annotations__
except AttributeError:
raise KeyError(key)
del annotation[key]
@@ -0,0 +1,11 @@
<configure xmlns="http://namespaces.zope.org/zope">
<include file="meta.zcml" package="zope.component" />
<adapter
for=".interfaces.IAttributeAnnotatable"
provides=".interfaces.IAnnotations"
factory=".attribute.AttributeAnnotations"
/>
</configure>
@@ -0,0 +1,57 @@
##############################################################################
#
# Copyright (c) 2006 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.
#
##############################################################################
"""Annotation factory helper
"""
import zope.component
import zope.interface
import zope.location.location
import zope.location.interfaces
import zope.proxy
import zope.annotation.interfaces
def factory(factory, key=None):
"""Adapter factory to help create annotations easily.
"""
# if no key is provided,
# we'll determine the unique key based on the factory's dotted name
if key is None:
key = factory.__module__ + '.' + factory.__name__
adapts = zope.component.adaptedBy(factory)
if adapts is None:
raise TypeError("Missing 'zope.component.adapts' on annotation")
@zope.component.adapter(list(adapts)[0])
@zope.interface.implementer(list(zope.component.implementedBy(factory))[0])
def getAnnotation(context):
annotations = zope.annotation.interfaces.IAnnotations(context)
try:
result = annotations[key]
except KeyError:
result = factory()
annotations[key] = result
if zope.location.interfaces.ILocation.providedBy(result):
zope.location.location.locate(result,
zope.proxy.removeAllProxies(context), key)
if not (zope.location.interfaces.ILocation.providedBy(result)
and result.__parent__ is context
and result.__name__ == key):
result = zope.location.location.LocationProxy(result, context, key)
return result
# Convention to make adapter introspectable, used by apidoc
getAnnotation.factory = factory
return getAnnotation
@@ -0,0 +1,101 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Annotations store arbitrary application data under package-unique keys.
"""
__docformat__ = 'restructuredtext'
from zope.interface import Interface
class IAnnotatable(Interface):
"""Marker interface for objects that support storing annotations.
This interface says "There exists an adapter to an IAnnotations
for an object that implements `IAnnotatable`".
Classes should not directly declare that they implement this interface.
Instead they should implement an interface derived from this one, which
details how the annotations are to be stored, such as
`IAttributeAnnotatable`.
"""
class IAnnotations(IAnnotatable):
"""Stores arbitrary application data under package-unique keys.
By "package-unique keys", we mean keys that are are unique by
virtue of including the dotted name of a package as a prefix. A
package name is used to limit the authority for picking names for
a package to the people using that package.
For example, when implementing annotations for storing Zope
Dublin-Core meta-data, we use the key::
"zope.app.dublincore.ZopeDublinCore"
"""
def __nonzero__():
"""Test whether there are any annotations
Must be identical to __bool__()
"""
def __bool__(): # Python 3 API.
"""Test whether there are any annotations
Must be identical to __nonzero__()
"""
def __getitem__(key):
"""Return the annotation stored under key.
Raises KeyError if key not found.
"""
def get(key, default=None):
"""Return the annotation stored under key, or default if not found.
"""
def __setitem__(key, value):
"""Store annotation under key.
In order to avoid key collisions, users of this interface must
use their dotted package name as part of the key name.
"""
def __delitem__(key):
"""Removes the annotation stored under key.
Raises a KeyError if the key is not found.
"""
def __iter__():
"""Return an iterator for the keys in the container.
"""
def __contains__(key):
"""Return True if 'key' is in the container, else False.
"""
def items():
"""Return '(key, value)' pairs for the keys in the container.
"""
class IAttributeAnnotatable(IAnnotatable):
"""Marker indicating that annotations can be stored on an attribute.
This is a marker interface giving permission for an `IAnnotations`
adapter to store data in an attribute named `__annotations__`.
"""
@@ -0,0 +1 @@
# Import this.
@@ -0,0 +1,90 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""General Annotations Tests
All objects implementing 'IAnnotations' should pass these tests. They might be
used as base tests for real implementations.
"""
from zope.interface.verify import verifyObject
from zope.annotation.interfaces import IAnnotations
class AnnotationsTestBase(object):
"""Test the IAnnotations interface.
The test case class expects the 'IAnnotations' implementer to be in
'self.annotations'.
"""
annotations = None
obj = None
def test_nonzero(self):
self.assertFalse(self.annotations)
self.annotations['unittest'] = self.obj
self.assertTrue(self.annotations)
del self.annotations['unittest']
self.assertFalse(self.annotations)
def testInterfaceVerifies(self):
verifyObject(IAnnotations, self.annotations)
def testStorage(self):
# test __getitem__
self.annotations['unittest'] = self.obj
res = self.annotations['unittest']
self.assertEqual(self.obj, res)
def testGetitemException(self):
# test __getitem__ raises exception on unknown key
self.assertRaises(KeyError, self.annotations.__getitem__,'randomkey')
def testGet(self):
# test get
self.annotations['unittest'] = self.obj
res = self.annotations.get('unittest')
self.assertEqual(self.obj, res)
def testGetNoSet(self):
# test get with no set
res = self.annotations.get('randomkey')
self.assertEqual(None, res)
def testGetDefault(self):
# test get returns default
res = self.annotations.get('randomkey', 'default')
self.assertEqual('default', res)
def testDel(self):
self.annotations['unittest'] = self.obj
del self.annotations['unittest']
self.assertEqual(None, self.annotations.get('unittest'))
self.assertEqual([], list(self.annotations.keys()))
self.assertEqual([], list(self.annotations))
self.assertEqual(0, len(self.annotations))
def testDelRaisesKeyError(self):
self.assertRaises(KeyError, self.annotations.__delitem__, 'unittest')
def testKeys(self):
self.assertEqual([], list(self.annotations.keys()))
self.annotations['unittest'] = self.obj
self.assertEqual(1, len(self.annotations))
self.assertEqual(['unittest'], list(self.annotations.keys()))
def testIter(self):
self.assertEqual([], list(self.annotations))
self.annotations['unittest'] = self.obj
self.assertEqual(1, len(self.annotations))
self.assertEqual(['unittest'], list(self.annotations))
self.assertEqual(1, len(self.annotations))
@@ -0,0 +1,45 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
import unittest
from zope.annotation.tests.annotations import AnnotationsTestBase
class AttributeAnnotationsTest(AnnotationsTestBase, unittest.TestCase):
def setUp(self):
from zope.testing import cleanup
from zope.interface import implementer
from zope.annotation.attribute import AttributeAnnotations
from zope.annotation.interfaces import IAttributeAnnotatable
cleanup.setUp()
@implementer(IAttributeAnnotatable)
class Dummy(object):
pass
self.obj = Dummy()
self.annotations = AttributeAnnotations(self.obj)
def tearDown(self):
from zope.testing import cleanup
cleanup.tearDown()
def testInterfaceVerifies(self):
super(AttributeAnnotationsTest, self).testInterfaceVerifies()
self.assertIs(self.obj, self.annotations.__parent__)
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)
@@ -0,0 +1,43 @@
##############################################################################
#
# Copyright (c) 2011 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.
#
##############################################################################
import unittest
class ZCMLTest(unittest.TestCase):
def test_configure_zcml_should_be_loadable(self):
from zope.configuration.xmlconfig import XMLConfig
import zope.annotation as MUT
XMLConfig('configure.zcml', MUT)()
def test_configure_should_register_n_components(self):
from zope.component import getGlobalSiteManager
from zope.configuration.xmlconfig import XMLConfig
import zope.annotation as MUT
gsm = getGlobalSiteManager()
u_count = len(list(gsm.registeredUtilities()))
a_count = len(list(gsm.registeredAdapters()))
s_count = len(list(gsm.registeredSubscriptionAdapters()))
h_count = len(list(gsm.registeredHandlers()))
XMLConfig( 'configure.zcml', MUT)()
self.assertEqual(u_count + 2, len(list(gsm.registeredUtilities())))
self.assertEqual(a_count + 1, len(list(gsm.registeredAdapters())))
self.assertEqual(
s_count, len(list(gsm.registeredSubscriptionAdapters())))
self.assertEqual(h_count, len(list(gsm.registeredHandlers())))
@@ -0,0 +1,120 @@
##############################################################################
#
# Copyright (c) 2017 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.
#
##############################################################################
import unittest
from zope.annotation import factory
from zope import interface
from zope import component
from zope.location.interfaces import ILocation
from zope.annotation.interfaces import IAnnotations
class ITarget(interface.Interface):
pass
class IContext(IAnnotations):
pass
@interface.implementer(ITarget)
@component.adapter(IContext)
class Target(object):
pass
@interface.implementer(IContext)
class Context(dict):
pass
class TestFactory(unittest.TestCase):
assertRaisesRegex = getattr(unittest.TestCase, 'assertRaisesRegex',
getattr(unittest.TestCase, 'assertRaisesRegexp'))
def test_no_adapts(self):
self.assertRaisesRegex(TypeError, "Missing.*on annotation",
factory, TestFactory)
def test_factory_no_location(self):
getAnnotation = factory(Target)
context = Context()
target = getAnnotation(context)
# Several things have happened now.
# First, we have an annotation, derived from
# our class name
key = 'zope.annotation.tests.test_factory.Target'
self.assertEqual([key],
list(context))
# Second, a target object is stored at that location.
self.assertEqual(type(context[key]), Target)
# Third, the returned object is an ILocation, rooted at the
# parent and having the given name.
self.assertTrue(ILocation.providedBy(target))
self.assertIs(target.__parent__, context)
self.assertEqual(target.__name__, key)
# But it's a proxy.
self.assertNotEqual(type(target), Target)
self.assertTrue(ITarget.providedBy(target))
def test_factory_location(self):
# Given an object that is a location,
# it is not proxied
@interface.implementer(ILocation)
class LocatedTarget(Target):
__name__ = None
__parent__ = None
getAnnotation = factory(LocatedTarget)
context = Context()
target = getAnnotation(context)
key = 'zope.annotation.tests.test_factory.LocatedTarget'
self.assertEqual([key],
list(context))
# Second, a target object is stored at that location.
self.assertEqual(type(context[key]), LocatedTarget)
# Third, the returned object is an ILocation, rooted at the
# parent and having the given name.
self.assertTrue(ILocation.providedBy(target))
self.assertIs(target.__parent__, context)
self.assertEqual(target.__name__, key)
# And it's not a proxy.
self.assertEqual(type(target), LocatedTarget)
self.assertTrue(ITarget.providedBy(target))
self.assertIs(target, context[key])
def test_factory_with_key(self):
key = 'testkey'
getAnnotation = factory(Target, key)
context = Context()
getAnnotation(context)
self.assertEqual([key],
list(context))
# Second, a target object is stored at that location.
self.assertEqual(type(context[key]), Target)
@@ -0,0 +1,96 @@
============
Interfaces
============
This package defines several basic interfaces.
.. currentmodule:: zope.browser.interfaces
IView
=====
Views adapt both a context and a request.
There is not much we can test except that ``IView`` is importable
and an interface:
>>> from zope.interface import Interface
>>> from zope.browser.interfaces import IView
>>> Interface.providedBy(IView)
True
.. autointerface:: IView
IBrowserView
============
Browser views are views specialized for requests from a browser (e.g.,
as distinct from WebDAV, FTP, XML-RPC, etc.).
There is not much we can test except that ``IBrowserView`` is importable
and an interface derived from :class:`IView`:
>>> from zope.interface import Interface
>>> from zope.browser.interfaces import IBrowserView
>>> Interface.providedBy(IBrowserView)
True
>>> IBrowserView.extends(IView)
True
.. autointerface:: IBrowserView
IAdding
=======
Adding views manage how newly-created items get added to containers.
There is not much we can test except that ``IAdding`` is importable
and an interface derived from :class:`IBrowserView`:
>>> from zope.interface import Interface
>>> from zope.browser.interfaces import IAdding
>>> Interface.providedBy(IBrowserView)
True
>>> IAdding.extends(IBrowserView)
True
.. autointerface:: IAdding
ITerms
======
The ``ITerms`` interface is used as a base for ``ISource`` widget
implementations. This interfaces get used by ``zope.app.form`` and was
initially defined in ``zope.app.form.browser.interfaces``, which made it
impossible to use for other packages like ``z3c.form`` wihtout depending on
``zope.app.form``.
Moving such base components / interfaces to ``zope.browser`` makes it
possible to share them without undesirable dependencies.
There is not much we can test except that ITerms is importable
and an interface:
>>> from zope.interface import Interface
>>> from zope.browser.interfaces import ITerms
>>> Interface.providedBy(ITerms)
True
.. autointerface:: ITerms
ISystemErrorView
================
Views providing this interface can classify their contexts as system
errors. These errors can be handled in a special way (e. g. more
detailed logging).
There is not much we can test except that ``ISystemErrorView`` is importable
and an interface:
>>> from zope.interface import Interface
>>> from zope.browser.interfaces import ISystemErrorView
>>> Interface.providedBy(ISystemErrorView)
True
.. autointerface:: ISystemErrorView
@@ -0,0 +1 @@
# make a package
@@ -0,0 +1,112 @@
##############################################################################
#
# Copyright (c) 2004-2009 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.
#
##############################################################################
"""Shared dependency less Zope3 brwoser components.
"""
__docformat__ = 'restructuredtext'
from zope.interface import Attribute
from zope.interface import Interface
class IView(Interface):
""" Views are multi-adapters for context and request objects.
"""
context = Attribute("The context object the view renders")
request = Attribute("The request object driving the view")
class IBrowserView(IView):
""" Views which are specialized for requests from a browser
Such views are distinct from those geerated via WebDAV, FTP, XML-RPC,
etc.
"""
class IAdding(IBrowserView):
""" Multi-adapter interface for views which add items to containers.
The 'context' of the view must implement :obj:`zope.container.interfaces.IContainer`.
"""
def add(content):
"""Add content object to context.
Add using the name in ``contentName``.
Return the added object in the context of its container.
If ``contentName`` is already used in container, raise
:class:`zope.container.interfaces.DuplicateIDError`.
"""
contentName = Attribute(
"""The content name, usually set by the Adder traverser.
If the content name hasn't been defined yet, returns ``None``.
Some creation views might use this to optionally display the
name on forms.
"""
)
def nextURL():
"""Return the URL that the creation view should redirect to.
This is called by the creation view after calling add.
It is the adder's responsibility, not the creation view's to
decide what page to display after content is added.
"""
def nameAllowed():
"""Return whether names can be input by the user.
"""
def addingInfo():
"""Return add menu data as a sequence of mappings.
Each mapping contains 'action', 'title', and possibly other keys.
The result is sorted by title.
"""
def isSingleMenuItem():
"""Return whether there is single menu item or not."""
def hasCustomAddView():
"This should be called only if there is ``singleMenuItem`` else return 0"
class ITerms(Interface):
""" Adapter providing lookups for vocabulary terms.
"""
def getTerm(value):
"""Return an ITitledTokenizedTerm object for the given value
LookupError is raised if the value isn't in the source.
The return value should have the ``token`` and ``title`` attributes.
"""
def getValue(token):
"""Return a value for a given identifier token
LookupError is raised if there isn't a value in the source.
"""
class ISystemErrorView(Interface):
"""Error views that can classify their contexts as system errors
"""
def isSystemError():
"""Return a boolean indicating whether the error is a system errror
"""
@@ -0,0 +1,29 @@
##############################################################################
#
# Copyright (c) 2007 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.
#
##############################################################################
"""Test Suite"""
import doctest
import unittest
def test_suite():
return unittest.TestSuite((
doctest.DocFileSuite(
'README.rst',
optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
),
))
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
@@ -0,0 +1 @@
from zope.browserpage.viewpagetemplatefile import ViewPageTemplateFile
@@ -0,0 +1,21 @@
<configure xmlns="http://namespaces.zope.org/zope">
<class class=".viewpagetemplatefile.BoundPageTemplate">
<allow attributes="__call__ __str__ __name__" />
</class>
<adapter
for="zope.browserpage.viewpagetemplatefile.BoundPageTemplate
zope.publisher.interfaces.browser.IBrowserRequest"
provides="zope.publisher.interfaces.browser.IBrowserPublisher"
factory="zope.browserpage.viewpagetemplatefile.NoTraverser"
/>
<!-- TALES namespace allows view/template:default etc -->
<adapter
for="*"
factory=".namedtemplate.NamedTemplatePathAdapter"
name="template"
/>
</configure>
@@ -0,0 +1,53 @@
<configure xmlns:meta="http://namespaces.zope.org/meta">
<meta:directives namespace="http://namespaces.zope.org/browser">
<meta:directive
name="page"
schema=".metadirectives.IPageDirective"
handler=".metaconfigure.page"
/>
<meta:complexDirective
name="pages"
schema=".metadirectives.IPagesDirective"
handler=".metaconfigure.pages"
>
<meta:subdirective
name="page"
schema=".metadirectives.IPagesPageSubdirective"
/>
</meta:complexDirective>
<meta:complexDirective
name="view"
schema=".metadirectives.IViewDirective"
handler=".metaconfigure.view"
>
<meta:subdirective
name="page"
schema=".metadirectives.IViewPageSubdirective"
/>
<meta:subdirective
name="defaultPage"
schema=".metadirectives.IViewDefaultPageSubdirective"
/>
</meta:complexDirective>
</meta:directives>
<meta:directives namespace="http://namespaces.zope.org/tales">
<meta:directive name="expressiontype"
schema=".metadirectives.IExpressionTypeDirective"
handler=".metaconfigure.expressiontype"
/>
</meta:directives>
</configure>
@@ -0,0 +1,459 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Browser page ZCML configuration code
"""
import os
from zope.component import queryMultiAdapter
from zope.component.interface import provideInterface
from zope.component.zcml import handler
from zope.interface import implementer, classImplements, Interface
from zope.publisher.interfaces import NotFound
from zope.security.checker import CheckerPublic, Checker, defineChecker
from zope.configuration.exceptions import ConfigurationError
from zope.pagetemplate.engine import Engine
from zope.pagetemplate.engine import _Engine
from zope.pagetemplate.engine import TrustedEngine
from zope.pagetemplate.engine import _TrustedEngine
from zope.publisher.interfaces.browser import IBrowserRequest
from zope.publisher.interfaces.browser import IDefaultBrowserLayer
from zope.publisher.interfaces.browser import IBrowserPublisher
from zope.publisher.browser import BrowserView
from zope.browserpage.simpleviewclass import SimpleViewClass
from zope.browserpage.viewpagetemplatefile import ViewPageTemplateFile
def _fallbackMenuItemDirective(_context, *args, **kwargs):
import warnings
warnings.warn_explicit(
'Page directive used with "menu" argument, while "zope.browsermenu" '
'package is not installed. Doing nothing.',
UserWarning,
_context.info.file, _context.info.line)
return []
try:
from zope.browsermenu.metaconfigure import menuItemDirective
except ImportError: # pragma: no cover
menuItemDirective = _fallbackMenuItemDirective
# There are three cases we want to suport:
#
# Named view without pages (single-page view)
#
# <browser:page
# for=".IContact.IContactInfo."
# name="info.html"
# template="info.pt"
# class=".ContactInfoView."
# permission="zope.View"
# />
#
# Unnamed view with pages (multi-page view)
#
# <browser:pages
# for=".IContact."
# class=".ContactEditView."
# permission="ZopeProducts.Contact.ManageContacts"
# >
#
# <browser:page name="edit.html" template="edit.pt" />
# <browser:page name="editAction.html" attribute="action" />
# </browser:pages>
#
# Named view with pages (add view is a special case of this)
#
# <browser:view
# name="ZopeProducts.Contact"
# for="Zope.App.OFS.Container.IAdding."
# class=".ContactAddView."
# permission="ZopeProducts.Contact.ManageContacts"
# >
#
# <browser:page name="add.html" template="add.pt" />
# <browser:page name="action.html" attribute="action" />
# </browser:view>
# We'll also provide a convenience directive for add views:
#
# <browser:add
# name="ZopeProducts.Contact"
# class=".ContactAddView."
# permission="ZopeProducts.Contact.ManageContacts"
# >
#
# <browser:page name="add.html" template="add.pt" />
# <browser:page name="action.html" attribute="action" />
# </browser:view>
# page
def _norm_template(_context, template):
template = os.path.abspath(str(_context.path(template)))
if not os.path.isfile(template):
raise ConfigurationError("No such file", template)
return template
def page(_context, name, permission, for_=Interface,
layer=IDefaultBrowserLayer, template=None, class_=None,
allowed_interface=None, allowed_attributes=None,
attribute='__call__', menu=None, title=None):
_handle_menu(_context, menu, title, [for_], name, permission, layer)
required = {}
permission = _handle_permission(_context, permission)
if not (class_ or template):
raise ConfigurationError("Must specify a class or template")
if attribute != '__call__':
if template:
raise ConfigurationError(
"Attribute and template cannot be used together.")
assert class_, "Must have class if attribute is used"
if template:
template = _norm_template(_context, template)
required['__getitem__'] = permission
# TODO: new __name__ attribute must be tested
if class_:
if attribute != '__call__':
if not hasattr(class_, attribute):
raise ConfigurationError(
"The provided class doesn't have the specified attribute "
)
if template:
# class and template
new_class = SimpleViewClass(template, bases=(class_, ), name=name)
else:
if not hasattr(class_, 'browserDefault'):
cdict = {
'browserDefault':
lambda self, request: (getattr(self, attribute), ())
}
else:
cdict = {}
cdict['__name__'] = name
cdict['__page_attribute__'] = attribute
new_class = type(class_.__name__, (class_, simple,), cdict)
if hasattr(class_, '__implements__'):
classImplements(new_class, IBrowserPublisher)
else:
# template
new_class = SimpleViewClass(template, name=name)
for n in (attribute, 'browserDefault', '__call__', 'publishTraverse'):
required[n] = permission
_handle_allowed_interface(_context, allowed_interface, permission,
required)
_handle_allowed_attributes(_context, allowed_attributes, permission,
required)
_handle_for(_context, for_)
defineChecker(new_class, Checker(required))
_context.action(
discriminator=('view', (for_, layer), name, IBrowserRequest),
callable=handler,
args=('registerAdapter',
new_class, (for_, layer), Interface, name, _context.info),
)
# pages, which are just a short-hand for multiple page directives.
# Note that a class might want to access one of the defined
# templates. If it does though, it should use getMultiAdapter.
class pages(object):
def __init__(self, _context, permission, for_=Interface,
layer=IDefaultBrowserLayer, class_=None,
allowed_interface=None, allowed_attributes=None):
self.opts = dict(
for_=for_, permission=permission,
layer=layer, class_=class_,
allowed_interface=allowed_interface,
allowed_attributes=allowed_attributes,
)
def page(self, _context, name, attribute='__call__', template=None,
menu=None, title=None):
return page(_context,
name=name,
attribute=attribute,
template=template,
menu=menu, title=title,
**(self.opts))
def __call__(self):
return ()
# view (named view with pages)
# This is a different case. We actually build a class with attributes
# for all of the given pages.
class view(object):
default = None
def __init__(self, _context, permission, for_=Interface,
name='', layer=IDefaultBrowserLayer, class_=None,
allowed_interface=None, allowed_attributes=None,
menu=None, title=None, provides=Interface):
_handle_menu(_context, menu, title, [for_], name, permission, layer)
permission = _handle_permission(_context, permission)
self.args = (_context, name, (for_, layer), permission, class_,
allowed_interface, allowed_attributes)
self.pages = []
self.menu = menu
self.provides = provides
def page(self, _context, name, attribute=None, template=None):
if template:
template = _norm_template(_context, template)
else:
if not attribute:
raise ConfigurationError(
"Must specify either a template or an attribute name")
self.pages.append((name, attribute, template))
return ()
def defaultPage(self, _context, name):
self.default = name
return ()
def __call__(self):
(_context, name, (for_, layer), permission, class_,
allowed_interface, allowed_attributes) = self.args
required = {}
cdict = {}
pages = {}
for pname, attribute, template in self.pages:
if template:
cdict[pname] = ViewPageTemplateFile(template)
if attribute and attribute != name:
cdict[attribute] = cdict[pname]
else:
if not hasattr(class_, attribute):
raise ConfigurationError("Undefined attribute",
attribute)
attribute = attribute or pname
required[pname] = permission
pages[pname] = attribute
# This should go away, but noone seems to remember what to do. :-(
if hasattr(class_, 'publishTraverse'):
def publishTraverse(self, request, name,
pages=pages, getattr=getattr):
if name in pages:
return getattr(self, pages[name])
view = queryMultiAdapter((self, request), name=name)
if view is not None:
return view
m = class_.publishTraverse.__get__(self)
return m(request, name)
else:
def publishTraverse(self, request, name,
pages=pages, getattr=getattr):
if name in pages:
return getattr(self, pages[name])
view = queryMultiAdapter((self, request), name=name)
if view is not None:
return view
raise NotFound(self, name, request)
cdict['publishTraverse'] = publishTraverse
if not hasattr(class_, 'browserDefault'):
if self.default or self.pages:
_default = self.default or self.pages[0][0]
cdict['browserDefault'] = (
lambda self, request, default=_default:
(self, (default, ))
)
elif providesCallable(class_):
cdict['browserDefault'] = (
lambda self, request: (self, ())
)
bases = (simple,) if class_ is None else (class_, simple)
try:
cname = str(name)
except Exception: # pragma: no cover
cname = "GeneratedClass"
cdict['__name__'] = name
newclass = type(cname, bases, cdict)
for n in ('publishTraverse', 'browserDefault', '__call__'):
required[n] = permission
_handle_allowed_interface(_context, allowed_interface, permission,
required)
_handle_allowed_attributes(_context, allowed_attributes, permission,
required)
_handle_for(_context, for_)
defineChecker(newclass, Checker(required))
if self.provides is not None:
_context.action(
discriminator=None,
callable=provideInterface,
args=('', self.provides)
)
_context.action(
discriminator=('view', (for_, layer), name, self.provides),
callable=handler,
args=('registerAdapter',
newclass, (for_, layer), self.provides, name,
_context.info),
)
def _handle_menu(_context, menu, title, for_, name, permission,
layer=IDefaultBrowserLayer):
if not menu and not title:
# Neither of them
return []
if not menu or not title:
# Only one or the other
raise ConfigurationError(
"If either menu or title are specified, they must "
"both be specified.")
if len(for_) != 1:
raise ConfigurationError(
"Menus can be specified only for single-view, not for "
"multi-views.")
return menuItemDirective(
_context, menu, for_[0], '@@' + name, title,
permission=permission, layer=layer)
def _handle_permission(_context, permission):
if permission == 'zope.Public':
permission = CheckerPublic
return permission
def _handle_allowed_interface(_context, allowed_interface, permission,
required):
# Allow access for all names defined by named interfaces
if allowed_interface:
for i in allowed_interface:
_context.action(
discriminator=None,
callable=provideInterface,
args=(None, i)
)
for name in i:
required[name] = permission
def _handle_allowed_attributes(_context, allowed_attributes, permission,
required):
# Allow access for all named attributes
if allowed_attributes:
for name in allowed_attributes:
required[name] = permission
def _handle_for(_context, for_):
if for_ is not None:
_context.action(
discriminator=None,
callable=provideInterface,
args=('', for_)
)
@implementer(IBrowserPublisher)
class simple(BrowserView):
def publishTraverse(self, request, name):
raise NotFound(self, name, request)
def __call__(self, *a, **k):
# If a class doesn't provide it's own call, then get the attribute
# given by the browser default.
attr = self.__page_attribute__
if attr == '__call__':
raise AttributeError("__call__")
meth = getattr(self, attr)
return meth(*a, **k)
def providesCallable(class_):
if hasattr(class_, '__call__'):
for c in class_.__mro__:
if '__call__' in c.__dict__:
return True
return False
def expressiontype(_context, name, handler):
_context.action(
discriminator=("tales:expressiontype", name),
callable=registerType,
args=(name, handler)
)
def registerType(name, handler):
Engine.registerType(name, handler)
TrustedEngine.registerType(name, handler)
def clear():
Engine.__init__()
_Engine(Engine)
TrustedEngine.__init__()
_TrustedEngine(TrustedEngine)
try:
from zope.testing.cleanup import addCleanUp
except ImportError: # pragma: no cover
pass
else:
addCleanUp(clear)
@@ -0,0 +1,211 @@
#############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""ZCML directives for defining browser pages
"""
from zope.interface import Interface
from zope.configuration.fields import GlobalObject, GlobalInterface
from zope.configuration.fields import Path, PythonIdentifier, MessageID
from zope.schema import TextLine
from zope.security.zcml import Permission
from zope.component.zcml import IBasicViewInformation
try:
from zope.browsermenu.field import MenuField
except ImportError: # avoid hard dependency on zope.browsermenu pragma: no cover
MenuField = TextLine
class IPagesDirective(IBasicViewInformation):
"""
Define multiple pages without repeating all of the parameters.
The pages directive allows multiple page views to be defined
without repeating the 'for', 'permission', 'class', 'layer',
'allowed_attributes', and 'allowed_interface' attributes.
"""
for_ = GlobalObject(
title=u"The interface or class this view is for.",
required=False
)
layer = GlobalObject(
title=u"The request interface or class this view is for.",
description=
u"Defaults to zope.publisher.interfaces.browser.IDefaultBrowserLayer.",
required=False
)
permission = Permission(
title=u"Permission",
description=u"The permission needed to use the view.",
required=True
)
class IViewDirective(IPagesDirective):
"""
The view directive defines a view that has subpages.
The pages provided by the defined view are accessed by first
traversing to the view name and then traversing to the page name.
"""
for_ = GlobalInterface(
title=u"The interface this view is for.",
required=False
)
name = TextLine(
title=u"The name of the view.",
description=u"The name shows up in URLs/paths. For example 'foo'.",
required=False,
default=u'',
)
menu = MenuField(
title=u"The browser menu to include the page (view) in.",
description=u"""
Many views are included in menus. It's convenient to name
the menu in the page directive, rather than having to give a
separate menuItem directive. 'zmi_views' is the menu most often
used in the Zope management interface.
This attribute will only work if zope.browsermenu is installed.
""",
required=False
)
title = MessageID(
title=u"The browser menu label for the page (view)",
description=u"""
This attribute must be supplied if a menu attribute is
supplied.
This attribute will only work if zope.browsermenu is installed.
""",
required=False
)
provides = GlobalInterface(
title=u"The interface this view provides.",
description=u"""
A view can provide an interface. This would be used for
views that support other views.""",
required=False,
default=Interface,
)
class IViewPageSubdirective(Interface):
"""
Subdirective to IViewDirective.
"""
name = TextLine(
title=u"The name of the page (view)",
description=u"""
The name shows up in URLs/paths. For example 'foo' or
'foo.html'. This attribute is required unless you use the
subdirective 'page' to create sub views. If you do not have
sub pages, it is common to use an extension for the view name
such as '.html'. If you do have sub pages and you want to
provide a view name, you shouldn't use extensions.""",
required=True
)
attribute = PythonIdentifier(
title=u"The name of the view attribute implementing the page.",
description=u"""
This refers to the attribute (method) on the view that is
implementing a specific sub page.""",
required=False
)
template = Path(
title=u"The name of a template that implements the page.",
description=u"""
Refers to a file containing a page template (should end in
extension '.pt' or '.html').""",
required=False
)
class IViewDefaultPageSubdirective(Interface):
"""
Subdirective to IViewDirective.
"""
name = TextLine(
title=u"The name of the page that is the default.",
description=u"""
The named page will be used as the default if no name is
specified explicitly in the path. If no defaultPage directive
is supplied, the default page will be the first page
listed.""",
required=True
)
class IPagesPageSubdirective(IViewPageSubdirective):
"""
Subdirective to IPagesDirective
"""
menu = MenuField(
title=u"The browser menu to include the page (view) in.",
description=u"""
Many views are included in menus. It's convenient to name the
menu in the page directive, rather than having to give a
separate menuItem directive.
This attribute will only work if zope.browsermenu is installed.
""",
required=False
)
title = MessageID(
title=u"The browser menu label for the page (view)",
description=u"""
This attribute must be supplied if a menu attribute is
supplied.
This attribute will only work if zope.browsermenu is installed.
""",
required=False
)
class IPageDirective(IPagesDirective, IPagesPageSubdirective):
"""
The page directive is used to create views that provide a single
url or page.
The page directive creates a new view class from a given template
and/or class and registers it.
"""
class IExpressionTypeDirective(Interface):
"""Register a new TALES expression type"""
name = TextLine(
title=u"Name",
description=u"""Name of the expression. This will also be used
as the prefix in actual TALES expressions.""",
required=True
)
handler = GlobalObject(
title=u"Handler",
description=u"""Handler is class that implements
zope.tales.interfaces.ITALESExpression.""",
required=True
)
@@ -0,0 +1,73 @@
##############################################################################
#
# Copyright (c) 2005-2009 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.
#
##############################################################################
"""
"""
from zope import component, interface
import zope.traversing.interfaces
class INamedTemplate(interface.Interface):
"""A template that is looked up by name
"""
class NamedTemplateImplementation(object):
def __init__(self, descriptor, view_type=None):
try:
descriptor.__get__
except AttributeError:
raise TypeError(
"NamedTemplateImplementation must be passed a descriptor."
)
self.descriptor = descriptor
interface.implementer(INamedTemplate)(self)
if view_type is not None:
component.adapter(view_type)(self)
def __call__(self, instance):
return self.descriptor.__get__(instance, instance.__class__)
class implementation(object):
def __init__(self, view_type=None):
self.view_type = view_type
def __call__(self, descriptor):
return NamedTemplateImplementation(descriptor, self.view_type)
class NamedTemplate(object):
def __init__(self, name):
self.__name__ = name
def __get__(self, instance, type=None):
if instance is None:
return self
return component.getAdapter(instance, INamedTemplate, self.__name__)
def __call__(self, instance, *args, **kw):
self.__get__(instance)(*args, **kw)
@interface.implementer(zope.traversing.interfaces.IPathAdapter)
class NamedTemplatePathAdapter(object):
def __init__(self, context):
self.context = context
def __getitem__(self, name):
return component.getAdapter(self.context, INamedTemplate, name)
@@ -0,0 +1,75 @@
===============
Named Templates
===============
We often want to be able to define view logic and view templates
independently. We'd like to be able to change the template used by a
form without being forced to modify the form.
Named templates provide templates that are registered as named view
adapters. To define a named template, use the `NamedTemplateImplementation`
constructor:
>>> from zope.browserpage import ViewPageTemplateFile
>>> from zope.browserpage.namedtemplate import (
... NamedTemplateImplementation)
>>> sample = ViewPageTemplateFile('tests/namedtemplate.pt')
>>> sample = NamedTemplateImplementation(sample)
Let's define a view that uses the named template. To use a named
template, use the NamedTemplate constructor, and give a template name:
>>> from zope.browserpage.namedtemplate import NamedTemplate
>>> class MyView:
... def __init__(self, context, request):
... self.context = context
... self.request = request
...
... __call__ = NamedTemplate('sample')
Normally, we'd register a named template for a view interface, to
allow it to be registered for multiple views. We'll just register it
for our view class.
>>> from zope import component
>>> component.provideAdapter(sample, [MyView], name='sample')
Now, with this in place, we should be able to use our view:
>>> class MyContent:
... def __init__(self, name):
... self.name = name
>>> from zope.publisher.browser import TestRequest
>>> view = MyView(MyContent('bob'), TestRequest())
>>> print(view(x=42).replace('\r\n', '\n'))
<html><body>
Hello bob
The URL is http://127.0.0.1
The positional arguments were ()
The keyword argument x is 42
</body></html>
<BLANKLINE>
The view type that a named template is to be used for can be supplied
when the named template is created:
>>> class MyView:
... def __init__(self, context, request):
... self.context = context
... self.request = request
...
... __call__ = NamedTemplate('sample2')
>>> sample = ViewPageTemplateFile('tests/namedtemplate.pt')
>>> sample = NamedTemplateImplementation(sample, MyView)
>>> component.provideAdapter(sample, name='sample2')
>>> view = MyView(MyContent('bob'), TestRequest())
>>> print(view(x=42).replace('\r\n', '\n'))
<html><body>
Hello bob
The URL is http://127.0.0.1
The positional arguments were ()
The keyword argument x is 42
</body></html>
<BLANKLINE>
@@ -0,0 +1,57 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Simple View Class
"""
__docformat__ = 'restructuredtext'
import sys
from zope.interface import implementer
from zope.publisher.browser import BrowserView
from zope.publisher.interfaces.browser import IBrowserPublisher
from zope.publisher.interfaces import NotFound
from zope.browserpage.viewpagetemplatefile import ViewPageTemplateFile
@implementer(IBrowserPublisher)
class simple(BrowserView):
def browserDefault(self, request):
return self, ()
def publishTraverse(self, request, name):
if name == 'index.html':
return self.index
raise NotFound(self, name, request)
def __getitem__(self, name):
return self.index.macros[name]
def __call__(self, *args, **kw):
return self.index(*args, **kw)
def SimpleViewClass(src, offering=None, used_for=None, bases=(), name=u''):
if offering is None:
offering = sys._getframe(1).f_globals
bases += (simple, )
class_ = type("SimpleViewClass from %s" % src, bases,
{'index': ViewPageTemplateFile(src, offering),
'__name__': name})
if used_for is not None:
class_.__used_for__ = used_for
return class_
@@ -0,0 +1,6 @@
<html><body>
Hello <span tal:replace="context/name" />
The URL is <span tal:replace="request/URL" />
The positional arguments were <span tal:replace="args" />
The keyword argument x is <span tal:replace="options/x" />
</body></html>
@@ -0,0 +1,19 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Sample Component
"""
from zope.browserpage import ViewPageTemplateFile
class C(object):
index = ViewPageTemplateFile('test.pt')
@@ -0,0 +1,18 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Simple Test View
"""
from zope.browserpage.simpleviewclass import SimpleViewClass
SimpleTestView = SimpleViewClass('testsimpleviewclass.pt')
@@ -0,0 +1 @@
<html><body></body></html>
@@ -0,0 +1,34 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Bound Page Template Tests
"""
import unittest
class Test(unittest.TestCase):
def testAttributes(self):
from zope.browserpage.tests.sample import C
C.index.__func__.foo = 1
self.assertEqual(C.index.macros, C.index.__func__.macros)
self.assertEqual(C.index.filename, C.index.__func__.filename)
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)
if __name__ == '__main__':
unittest.TextTestRunner().run(test_suite())
@@ -0,0 +1,55 @@
##############################################################################
#
# Copyright (c) 2003 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.
#
##############################################################################
"""Tests to check talesapi zcml configuration
"""
import unittest
from io import StringIO
from zope.configuration.xmlconfig import xmlconfig, XMLConfig
from zope.pagetemplate.engine import Engine
import zope.browserpage
from zope.component.testing import PlacelessSetup
template = u"""<configure
xmlns='http://namespaces.zope.org/zope'
xmlns:tales='http://namespaces.zope.org/tales'>
%s
</configure>"""
class Handler(object):
pass
class Test(PlacelessSetup, unittest.TestCase):
def setUp(self):
super(Test, self).setUp()
XMLConfig('meta.zcml', zope.browserpage)()
def testExpressionType(self):
xmlconfig(StringIO(
template %
u"""
<tales:expressiontype
name="test"
handler="zope.browserpage.tests.test_expressiontype.Handler"
/>
"""
))
self.assertIn("test", Engine.getTypes())
self.assertIs(Handler, Engine.getTypes()['test'])
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)
@@ -0,0 +1,260 @@
##############################################################################
#
# Copyright (c) 2017 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.
#
##############################################################################
import unittest
from zope.browserpage.metaconfigure import page
from zope.browserpage.metaconfigure import view
from zope.browserpage.metaconfigure import simple
from zope.browserpage.metaconfigure import _handle_menu
from zope.configuration.exceptions import ConfigurationError
class Context(object):
class info(object):
file = __file__
line = 1
def __init__(self):
self.actions = []
def path(self, s):
return s
def action(self, **kwargs):
self.actions.append(kwargs)
class _AbstractHandlerTest(unittest.TestCase):
if not hasattr(unittest.TestCase, 'assertRaisesRegex'):
assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
def setUp(self):
self.context = Context()
def _call(self, **kwargs):
context = self.context
self._callFUT(context, 'Name', None, **kwargs)
return context
def _check_raises(self, regex, **kwargs):
with self.assertRaisesRegex(ConfigurationError, regex):
self._call(**kwargs)
class TestPage(_AbstractHandlerTest):
def _callFUT(self, *args, **kwargs):
page(*args, **kwargs)
def test_no_class_no_template(self):
self._check_raises('Must specify a class or template')
def test_template_attribute(self):
self._check_raises(
'Attribute and template cannot be used together',
template=self, attribute="attr")
def test_template_not_exists(self):
self._check_raises(
"No such file",
template=__name__)
def test_class_missing_attribute(self):
self._check_raises(
"The provided class doesn't have the specified attribute",
class_=type(self), attribute="does not exist")
def test_class_with_browser_default(self):
class BrowserDefault(object):
def browserDefault(self):
raise AssertionError("Not called")
context = self._call(
class_=BrowserDefault)
action = context.actions[1]
register = action['args']
new_class = register[1]
self.assertEqual(new_class.browserDefault,
BrowserDefault.browserDefault)
def test_class_implements(self):
from zope.publisher.interfaces.browser import IBrowserPublisher
from zope import interface
class Class(object):
# How does this arise in the wild?
# @implementer(IThing) doesn't do it.
__implements__ = None
self.assertTrue(hasattr(Class, '__implements__'))
context = self._call(class_=Class)
action = context.actions[1]
register = action['args']
new_class = register[1]
self.assertIn(IBrowserPublisher, interface.implementedBy(new_class))
class TestViewPage(_AbstractHandlerTest):
view = None
def _callFUT(self, *args, **kwargs):
self.view = view(self.context, None)
self.view.page(self.context, 'Name', **kwargs)
def test_no_attribute(self):
self._check_raises(
"Must specify either a template or an attribute name")
class TestView(_AbstractHandlerTest):
def test_class_without_attribute(self):
v = view(self.context, None, class_=type(self))
v.pages.append([None, 'does not exist', None])
self._call = v
self._check_raises('Undefined attribute')
def test_class_without_publish_traverse_name(self):
class C(object):
attr = 'the attr'
v = view(self.context, None, class_=C)
v.pages.append(['page_name', 'attr', None])
v()
action = self.context.actions[2]
register = action['args']
new_class = register[1]
instance = new_class(None, None)
self.assertEqual(C.attr,
instance.publishTraverse(None, 'page_name'))
with self.assertRaises(LookupError):
instance.publishTraverse(None, 'something else')
def test_class_with_publish_traverse_name(self):
class C(object):
attr = 'the attr'
def publishTraverse(self, *args):
raise AssertionError("Never called")
v = view(self.context, None, class_=C)
v.pages.append(['page_name', 'attr', None])
v()
action = self.context.actions[2]
register = action['args']
new_class = register[1]
instance = new_class(None, None)
self.assertEqual(C.attr,
instance.publishTraverse(None, 'page_name'))
def test_class_with_publish_traverse_other_name(self):
class C(object):
attr = 'the attr'
def publishTraverse(self, *args):
return 'default value'
v = view(self.context, None, class_=C)
v.pages.append(['page_name', 'attr', None])
v()
action = self.context.actions[2]
register = action['args']
new_class = register[1]
instance = new_class(None, None)
self.assertEqual('default value',
instance.publishTraverse(None, 'something else'))
def test_template_with_attr_not_equal_name(self):
import os
v = view(self.context, None)
v.page(self.context, 'page_name', attribute='foo',
template=os.path.join(os.path.dirname(__file__), 'test.pt'))
v()
action = self.context.actions[2]
register = action['args']
new_class = register[1]
self.assertTrue(hasattr(new_class, 'foo'))
self.assertTrue(hasattr(new_class, 'page_name'))
class TestHandleMenu(_AbstractHandlerTest):
def _call(self, **kwargs):
args = {
'_context': self.context,
'menu': None,
'title': None,
'for_': None,
'name': '',
'permission': None
}
args.update(kwargs)
return _handle_menu(**args)
def test_one_or_the_other(self):
self._check_raises(
".*they must both be specified",
menu='menu', title='')
self._check_raises(
".*they must both be specified",
menu='', title='menu')
def test_bad_for(self):
self._check_raises(
"Menus can be specified only for single-view",
menu='menu', title='title',
for_=(1, 2)
)
def test_no_directive(self):
from zope.browserpage import metaconfigure
import warnings
menuItemDirective = metaconfigure.menuItemDirective
metaconfigure.menuItemDirective = metaconfigure._fallbackMenuItemDirective
try:
with warnings.catch_warnings(record=True) as w:
result = self._call(menu='menu', title='title', for_=(1,))
self.assertEqual(result, [])
self.assertEqual(
'Page directive used with "menu" argument, while "zope.browsermenu" '
'package is not installed. Doing nothing.',
str(w[0].message))
finally:
metaconfigure.menuItemDirective = menuItemDirective
class TestSimple(unittest.TestCase):
def test_publish_not_found(self):
sview = simple(None, None)
with self.assertRaises(LookupError):
sview.publishTraverse(None, None)
def test_recursive_call(self):
sview = simple(None, None)
sview.__page_attribute__ = '__call__'
with self.assertRaises(AttributeError):
sview()
@@ -0,0 +1,88 @@
##############################################################################
#
# Copyright (c) 2005-2009 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.
#
##############################################################################
"""
"""
import os
import os.path
import unittest
from zope.browserpage import namedtemplate
import zope.component.testing
import zope.traversing.adapters
class TestImplementation(unittest.TestCase):
def test_call(self):
inst = namedtemplate.implementation(None)
nt = namedtemplate.NamedTemplate('name')
nti = inst(nt)
self.assertEqual(nti.descriptor, nt)
class TestNamedTemplateImplementation(unittest.TestCase):
def test_bad_descriptor(self):
with self.assertRaises(TypeError):
namedtemplate.NamedTemplateImplementation(None)
class TestNamedTemplate(unittest.TestCase):
def test_no_instance(self):
class X(object):
nt = namedtemplate.NamedTemplate('name')
self.assertIsInstance(X.nt, namedtemplate.NamedTemplate)
def test_call_no_adapter(self):
class X(object):
nt = namedtemplate.NamedTemplate('name')
with self.assertRaises(LookupError):
getattr(X(), 'nt')
with self.assertRaises(LookupError):
X.nt(X())
class TestNamedTemplatePathAdapter(unittest.TestCase):
def test_getitem_no_adapter(self):
adapter = namedtemplate.NamedTemplatePathAdapter(self)
with self.assertRaises(LookupError):
_ = adapter['name']
def pageSetUp(test):
zope.component.testing.setUp(test)
zope.component.provideAdapter(
zope.traversing.adapters.DefaultTraversable,
[None],
)
def test_suite():
import doctest
filename = os.path.join(os.pardir, 'namedtemplate.rst')
return unittest.TestSuite([
unittest.defaultTestLoader.loadTestsFromName(__name__),
doctest.DocFileSuite(
filename,
setUp=pageSetUp, tearDown=zope.component.testing.tearDown,
globs={'__file__': os.path.abspath(os.path.join(os.path.dirname(__file__), filename))}
)
])
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,177 @@
##############################################################################
#
# Copyright (c) 2001-2009 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.
#
##############################################################################
"""Simple View Class Tests
"""
import unittest
class Test_SimpleTestView(unittest.TestCase):
def _getTargetClass(self):
from zope.browserpage.tests.simpletestview import SimpleTestView
return SimpleTestView
def _makeOne(self, context, request):
return self._getTargetClass()(context, request)
def test_simple(self):
from zope.publisher.browser import TestRequest
context = DummyContext()
request = TestRequest()
view = self._makeOne(context, request)
self.assertIsNotNone(view['test'])
out = view()
self.assertEqual(out.replace('\r\n', '\n'),
'<html>\n'
' <body>\n'
' <p>hello world</p>\n'
' </body>\n</html>\n')
class Test_SimpleViewClass(unittest.TestCase):
def _getTargetClass(self):
from zope.browserpage.simpleviewclass import SimpleViewClass
return SimpleViewClass
def _makeKlass(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test___name__(self):
klass = self._makeKlass('testsimpleviewclass.pt', name='test.html')
view = klass(None, None)
self.assertEqual(view.__name__, 'test.html')
def test__used_for__(self):
klass = self._makeKlass('testsimpleviewclass.pt',
name='test.html',
used_for=self)
self.assertIs(klass.__used_for__, self)
def test___getitem___(self):
klass = self._makeKlass('testsimpleviewclass.pt', name='test.html')
view = klass(None, None)
self.assertTrue(view['test'] is not None)
self.assertRaises(KeyError, view.__getitem__, 'foo')
def test_w_base_classes(self):
from zope.publisher.browser import TestRequest
class BaseClass(object):
pass
klass = self._makeKlass('testsimpleviewclass.pt', bases=(BaseClass, ))
self.assertTrue(issubclass(klass, BaseClass))
ob = DummyContext()
request = TestRequest()
view = klass(ob, request)
self.assertIsNotNone(view['test'])
out = view()
self.assertEqual(out.replace('\r\n', '\n'),
'<html>\n'
' <body>\n'
' <p>hello world</p>\n'
' </body>\n</html>\n')
class Test_simple(unittest.TestCase):
def _getTargetClass(self):
from zope.browserpage.simpleviewclass import simple
return simple
def _makeOne(self, context=None, request=None):
if context is None:
context = DummyContext()
if request is None:
request = DummyRequest()
return self._getTargetClass()(context, request)
def test_class_conforms_to_IBrowserPublisher(self):
from zope.interface.verify import verifyClass
from zope.publisher.interfaces.browser import IBrowserPublisher
verifyClass(IBrowserPublisher, self._getTargetClass())
def test_browserDefault(self):
request = DummyRequest()
view = self._makeOne(request=request)
self.assertEqual(view.browserDefault(request), (view, ()))
def test_publishTraverse_not_index_raises_NotFound(self):
from zope.publisher.interfaces import NotFound
request = DummyRequest()
view = self._makeOne(request=request)
self.assertRaises(NotFound, view.publishTraverse, request, 'nonesuch')
def test_publishTraverse_w_index_returns_index(self):
request = DummyRequest()
view = self._makeOne(request=request)
index = view.index = DummyTemplate()
self.assertTrue(view.publishTraverse(request, 'index.html') is index)
def test___getitem___uses_index_macros(self):
view = self._makeOne()
view.index = index = DummyTemplate()
index.macros = {}
index.macros['aaa'] = aaa = object()
self.assertTrue(view['aaa'] is aaa)
def test___call___no_args_no_kw(self):
view = self._makeOne()
view.index = index = DummyTemplate()
result = view()
self.assertTrue(result is index)
self.assertEqual(index._called_with, ((), {}))
def test___call___w_args_no_kw(self):
view = self._makeOne()
view.index = index = DummyTemplate()
result = view('abc')
self.assertTrue(result is index)
self.assertEqual(index._called_with, (('abc',), {}))
def test___call___no_args_w_kw(self):
view = self._makeOne()
view.index = index = DummyTemplate()
result = view(foo='bar')
self.assertTrue(result is index)
self.assertEqual(index._called_with, ((), {'foo': 'bar'}))
def test___call___w_args_w_kw(self):
view = self._makeOne()
view.index = index = DummyTemplate()
result = view('abc', foo='bar')
self.assertTrue(result is index)
self.assertEqual(index._called_with, (('abc',), {'foo': 'bar'}))
class DummyContext:
pass
class DummyResponse:
pass
class DummyRequest:
debug = False
response = DummyResponse()
class DummyTemplate:
def __call__(self, *args, **kw):
self._called_with = (args, kw)
return self
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(Test_SimpleTestView),
unittest.makeSuite(Test_SimpleViewClass),
unittest.makeSuite(Test_simple),
))
@@ -0,0 +1,175 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""View ZPT Tests
"""
import unittest
from zope.component import getGlobalSiteManager
from zope.component.testing import PlacelessSetup
from zope.interface import Interface, implementer
from zope.browserpage.viewpagetemplatefile import ViewPageTemplateFile
from zope.browserpage.viewpagetemplatefile import BoundPageTemplate
class I1(Interface):
pass
@implementer(I1)
class C1(object):
pass
class InstanceWithContext(object):
def __init__(self, context):
self.context = context
class InstanceWithoutContext(object):
pass
class TestViewZPT(PlacelessSetup, unittest.TestCase):
def setUp(self):
super(TestViewZPT, self).setUp()
self.t = ViewPageTemplateFile('test.pt')
self.context = C1()
def testNamespaceContextAvailable(self):
context = self.context
request = None
namespace = self.t.pt_getContext(InstanceWithContext(context), request)
self.assertTrue(namespace['context'] is context)
self.assertTrue('views' in namespace)
def testNamespaceHereNotAvailable(self):
request = None
self.assertRaises(AttributeError, self.t.pt_getContext,
InstanceWithoutContext(), request)
def testViewMapper(self):
the_view = "This is the view"
the_view_name = "some view name"
def ViewMaker(*args, **kw):
return the_view
from zope.publisher.interfaces import IRequest
gsm = getGlobalSiteManager()
gsm.registerAdapter(
ViewMaker, (I1, IRequest), Interface, the_view_name, event=False)
@implementer(IRequest)
class MyRequest(object):
pass
request = MyRequest()
namespace = self.t.pt_getContext(InstanceWithContext(self.context),
request)
views = namespace['views']
self.assertTrue(the_view is views[the_view_name])
def test_debug_flags(self):
from zope.publisher.browser import TestRequest
self.request = TestRequest()
self.request.debug.sourceAnnotations = False
self.assertFalse('test.pt' in self.t(self))
self.request.debug.sourceAnnotations = True
self.assertTrue('test.pt' in self.t(self))
t = ViewPageTemplateFile('testsimpleviewclass.pt')
self.request.debug.showTAL = False
self.assertFalse('metal:' in t(self))
self.request.debug.showTAL = True
self.assertTrue('metal:' in t(self))
def test_render_sets_content_type_unless_set(self):
from zope.publisher.browser import TestRequest
t = ViewPageTemplateFile('test.pt')
self.request = TestRequest()
response = self.request.response
self.assertFalse(response.getHeader('Content-Type'))
t(self)
self.assertEqual(response.getHeader('Content-Type'), 'text/html')
self.request = TestRequest()
response = self.request.response
response.setHeader('Content-Type', 'application/x-test-junk')
t(self)
self.assertEqual(response.getHeader('Content-Type'),
'application/x-test-junk')
class TestViewZPTContentType(unittest.TestCase):
def testInitWithoutType(self):
t = ViewPageTemplateFile('test.pt')
t._cook_check()
self.assertEqual(t.content_type, "text/html")
t = ViewPageTemplateFile('testxml.pt')
t._cook_check()
self.assertEqual(t.content_type, "text/xml")
def testInitWithType(self):
t = ViewPageTemplateFile('test.pt', content_type="text/plain")
t._cook_check()
self.assertEqual(t.content_type, "text/plain")
t = ViewPageTemplateFile('testxml.pt', content_type="text/plain")
t._cook_check()
self.assertEqual(t.content_type, "text/xml")
class TestBoundPageTemplate(unittest.TestCase):
def test_call_self_none(self):
args = []
def func(*a):
args.extend(a)
bpt = BoundPageTemplate(func, None)
bpt(self, 1, 2)
self.assertEqual(args, [self, 1, 2])
def test_cannot_set_attr(self):
bpt = BoundPageTemplate(None, None)
with self.assertRaises(AttributeError):
bpt.thing = 1
with self.assertRaises(AttributeError):
bpt.__func__ = 1
with self.assertRaises(AttributeError):
bpt.__self__ = 1
def test_repr(self):
ob = "WackyWavingInflatableArmFlailingTubeMan"
bpt = BoundPageTemplate(None, ob)
self.assertEqual(repr(bpt),
"<BoundPageTemplateFile of 'WackyWavingInflatableArmFlailingTubeMan'>")
class TestNoTraverser(unittest.TestCase):
def test_none(self):
from zope.browserpage.viewpagetemplatefile import NoTraverser
self.assertIsNone(NoTraverser(self, self))
def test_suite():
return unittest.defaultTestLoader.loadTestsFromName(__name__)
@@ -0,0 +1 @@
<html><body><p>test</p></body></html>
@@ -0,0 +1 @@
<html><body><p tal:content="view/data">test</p></body></html>
@@ -0,0 +1 @@
<html><body><p tal:content="view/action">test</p></body></html>
@@ -0,0 +1,5 @@
<html>
<body>
<p metal:define-macro="test">hello world</p>
</body>
</html>
@@ -0,0 +1,2 @@
<?xml version="1.0" ?>
<html><body></body></html>
@@ -0,0 +1,90 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""File-based page templates that can be used as methods on views.
"""
__docformat__ = 'restructuredtext'
from zope.component import getMultiAdapter
from zope.pagetemplate.pagetemplatefile import PageTemplateFile
from zope.pagetemplate.engine import TrustedAppPT
class ViewPageTemplateFile(TrustedAppPT, PageTemplateFile):
"""Page Templates used as methods of views defined as Python classes.
"""
def __init__(self, filename, _prefix=None, content_type=None):
_prefix = self.get_path_from_prefix(_prefix)
super(ViewPageTemplateFile, self).__init__(filename, _prefix)
if content_type is not None:
self.content_type = content_type
def pt_getContext(self, instance, request, **_kw):
# instance is a View component
namespace = super(ViewPageTemplateFile, self).pt_getContext(**_kw)
namespace['request'] = request
namespace['view'] = instance
namespace['context'] = context = instance.context
namespace['views'] = ViewMapper(context, request)
return namespace
def __call__(self, instance, *args, **keywords):
namespace = self.pt_getContext(
request=instance.request,
instance=instance, args=args, options=keywords)
debug_flags = instance.request.debug
s = self.pt_render(
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)
return s
def __get__(self, instance, type):
return BoundPageTemplate(self, instance)
class ViewMapper(object):
def __init__(self, ob, request):
self.ob = ob
self.request = request
def __getitem__(self, name):
return getMultiAdapter((self.ob, self.request), name=name)
class BoundPageTemplate(object):
def __init__(self, pt, ob):
object.__setattr__(self, '__func__', pt)
object.__setattr__(self, '__self__', ob)
macros = property(lambda self: self.__func__.macros)
filename = property(lambda self: self.__func__.filename)
def __call__(self, *args, **kw):
if self.__self__ is None:
im_self, args = args[0], args[1:]
else:
im_self = self.__self__
return self.__func__(im_self, *args, **kw)
def __setattr__(self, name, v):
raise AttributeError("Can't set attribute", name)
def __repr__(self):
return "<BoundPageTemplateFile of %r>" % self.__self__
def NoTraverser(ob, request):
return None
@@ -0,0 +1,61 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Zope 3 Component Architecture
"""
from zope.interface import Interface
from zope.interface import implementedBy
from zope.interface import moduleProvides
from zope.interface import named
from zope.interface import providedBy
from zope.interface.interfaces import ComponentLookupError
from zope.component.interfaces import IComponentArchitecture
from zope.interface.interfaces import IComponentLookup
from zope.component.interfaces import IComponentRegistrationConvenience
from zope.component.interfaces import IFactory
from zope.component.globalregistry import getGlobalSiteManager
from zope.component.globalregistry import globalSiteManager
from zope.component.globalregistry import provideAdapter
from zope.component.globalregistry import provideHandler
from zope.component.globalregistry import provideSubscriptionAdapter
from zope.component.globalregistry import provideUtility
from zope.component._api import adapter_hook
from zope.component._api import createObject
from zope.component._api import getAdapter
from zope.component._api import getAdapterInContext
from zope.component._api import getAdapters
from zope.component._api import getAllUtilitiesRegisteredFor
from zope.component._api import getFactoriesFor
from zope.component._api import getFactoryInterfaces
from zope.component._api import getMultiAdapter
from zope.component._api import getSiteManager
from zope.component._api import getUtilitiesFor
from zope.component._api import getUtility
from zope.component._api import getNextUtility
from zope.component._api import handle
from zope.component._api import queryAdapter
from zope.component._api import queryAdapterInContext
from zope.component._api import queryMultiAdapter
from zope.component._api import queryUtility
from zope.component._api import queryNextUtility
from zope.component._api import subscribers
from zope.component._declaration import adaptedBy
from zope.component._declaration import adapter
from zope.component._declaration import adapts
moduleProvides(IComponentArchitecture, IComponentRegistrationConvenience)
__all__ = tuple(IComponentArchitecture)
@@ -0,0 +1,231 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Zope 3 Component Architecture
"""
import sys
from zope.hookable import hookable
from zope.interface import Interface
from zope.interface.interfaces import ComponentLookupError
from zope.interface.interfaces import IComponentLookup
from zope.component.interfaces import IFactory
# getSiteManager() returns a component registry. Although the term
# "site manager" is deprecated in favor of "component registry",
# the old term is kept around to maintain a stable API.
base = None
@hookable
def getSiteManager(context=None):
""" See IComponentArchitecture.
"""
global base
if context is None:
if base is None:
from zope.component.globalregistry import base
return base
else:
# Use the global site manager to adapt context to `IComponentLookup`
# to avoid the recursion implied by using a local `getAdapter()` call.
try:
return IComponentLookup(context)
except TypeError as error:
raise ComponentLookupError(*error.args)
# Adapter API
def getAdapterInContext(object, interface, context):
adapter = queryAdapterInContext(object, interface, context)
if adapter is None:
raise ComponentLookupError(object, interface)
return adapter
def queryAdapterInContext(object, interface, context, default=None):
conform = getattr(object, '__conform__', None)
if conform is not None:
try:
adapter = conform(interface)
except TypeError:
# We got a TypeError. It might be an error raised by
# the __conform__ implementation, or *we* may have
# made the TypeError by calling an unbound method
# (object is a class). In the later case, we behave
# as though there is no __conform__ method. We can
# detect this case by checking whether there is more
# than one traceback object in the traceback chain:
if sys.exc_info()[2].tb_next is not None:
# There is more than one entry in the chain, so
# reraise the error:
raise
# This clever trick is from Phillip Eby
else:
if adapter is not None:
return adapter
if interface.providedBy(object):
return object
return getSiteManager(context).queryAdapter(object, interface, '', default)
def getAdapter(object, interface=Interface, name=u'', context=None):
adapter = queryAdapter(object, interface, name, None, context)
if adapter is None:
raise ComponentLookupError(object, interface, name)
return adapter
def queryAdapter(object, interface=Interface, name=u'', default=None,
context=None):
if context is None:
return adapter_hook(interface, object, name, default)
return getSiteManager(context).queryAdapter(object, interface, name,
default)
def getMultiAdapter(objects, interface=Interface, name=u'', context=None):
adapter = queryMultiAdapter(objects, interface, name, context=context)
if adapter is None:
raise ComponentLookupError(objects, interface, name)
return adapter
def queryMultiAdapter(objects, interface=Interface, name=u'', default=None,
context=None):
try:
sitemanager = getSiteManager(context)
except ComponentLookupError:
# Oh blast, no site manager. This should *never* happen!
return default
return sitemanager.queryMultiAdapter(objects, interface, name, default)
def getAdapters(objects, provided, context=None):
try:
sitemanager = getSiteManager(context)
except ComponentLookupError:
# Oh blast, no site manager. This should *never* happen!
return []
return sitemanager.getAdapters(objects, provided)
def subscribers(objects, interface, context=None):
try:
sitemanager = getSiteManager(context)
except ComponentLookupError:
# Oh blast, no site manager. This should *never* happen!
return []
return sitemanager.subscribers(objects, interface)
def handle(*objects):
getSiteManager(None).subscribers(objects, None)
#############################################################################
# Register the component architectures adapter hook, with the adapter hook
# registry of the `zope.inteface` package. This way we will be able to call
# interfaces to create adapters for objects. For example, `I1(ob)` is
# equvalent to `getAdapterInContext(I1, ob, '')`.
@hookable
def adapter_hook(interface, object, name='', default=None):
try:
sitemanager = getSiteManager()
except ComponentLookupError: #pragma NO COVER w/o context, cannot test
# Oh blast, no site manager. This should *never* happen!
return None
return sitemanager.queryAdapter(object, interface, name, default)
import zope.interface.interface
zope.interface.interface.adapter_hooks.append(adapter_hook)
#############################################################################
# Utility API
def getUtility(interface, name='', context=None):
utility = queryUtility(interface, name, context=context)
if utility is not None:
return utility
raise ComponentLookupError(interface, name)
def queryUtility(interface, name='', default=None, context=None):
return getSiteManager(context).queryUtility(interface, name, default)
def getUtilitiesFor(interface, context=None):
return getSiteManager(context).getUtilitiesFor(interface)
def getAllUtilitiesRegisteredFor(interface, context=None):
return getSiteManager(context).getAllUtilitiesRegisteredFor(interface)
_marker = object()
def queryNextUtility(context, interface, name='', default=None):
"""Query for the next available utility.
Find the next available utility providing `interface` and having the
specified name. If no utility was found, return the specified `default`
value.
"""
try:
sm = getSiteManager(context)
except ComponentLookupError:
return default
bases = sm.__bases__
for base in bases:
util = base.queryUtility(interface, name, _marker)
if util is not _marker:
return util
return default
def getNextUtility(context, interface, name=''):
"""Get the next available utility.
If no utility was found, a `ComponentLookupError` is raised.
"""
util = queryNextUtility(context, interface, name, _marker)
if util is _marker:
raise ComponentLookupError(
"No more utilities for %s, '%s' have been found." % (
interface, name))
return util
# Factories
def createObject(__factory_name, *args, **kwargs):
"""Invoke the named factory and return the result.
``__factory_name`` is a positional-only argument.
"""
context = kwargs.pop('context', None)
return getUtility(IFactory, __factory_name, context)(*args, **kwargs)
def getFactoryInterfaces(name, context=None):
"""Return the interface provided by the named factory's objects
Result might be a single interface. XXX
"""
return getUtility(IFactory, name, context).getInterfaces()
def getFactoriesFor(interface, context=None):
"""Return info on all factories implementing the given interface.
"""
utils = getSiteManager(context)
for (name, factory) in utils.getUtilitiesFor(IFactory):
interfaces = factory.getInterfaces()
try:
if interfaces.isOrExtends(interface):
yield name, factory
except AttributeError:
for iface in interfaces:
if iface.isOrExtends(interface):
yield name, factory
break
@@ -0,0 +1,34 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
import sys
import types
if sys.version_info[0] < 3: #pragma NO COVER
import cPickle as _pickle
CLASS_TYPES = (type, types.ClassType)
PYTHON3 = False
PYTHON2 = True
else: #pragma NO COVER
import pickle as _pickle
CLASS_TYPES = (type,)
PYTHON3 = True
PYTHON2 = False
@@ -0,0 +1,59 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Adapter declarations
"""
import sys
from zope.component._compat import CLASS_TYPES
class adapter(object):
def __init__(self, *interfaces):
self.interfaces = interfaces
def __call__(self, ob):
if isinstance(ob, CLASS_TYPES):
ob.__component_adapts__ = _adapts_descr(self.interfaces)
else:
ob.__component_adapts__ = self.interfaces
return ob
def adapts(*interfaces):
frame = sys._getframe(1)
locals = frame.f_locals
# Ensure we were called from a class def.
if locals is frame.f_globals or '__module__' not in locals:
raise TypeError("adapts can be used only from a class definition.")
if '__component_adapts__' in locals:
raise TypeError("adapts can be used only once in a class definition.")
locals['__component_adapts__'] = _adapts_descr(interfaces)
def adaptedBy(ob):
return getattr(ob, '__component_adapts__', None)
def getName(ob):
return getattr(ob, '__component_name__', u'')
class _adapts_descr(object):
def __init__(self, interfaces):
self.interfaces = interfaces
def __get__(self, inst, cls):
if inst is None:
return self.interfaces
raise AttributeError('__component_adapts__')
@@ -0,0 +1,12 @@
<configure xmlns="http://namespaces.zope.org/zope">
<include file="meta.zcml" />
<subscriber handler=".event.objectEventNotify" />
<subscriber handler=".registry.dispatchUtilityRegistrationEvent" />
<subscriber handler=".registry.dispatchAdapterRegistrationEvent" />
<subscriber handler=".registry.dispatchSubscriptionAdapterRegistrationEvent" />
<subscriber handler=".registry.dispatchHandlerRegistrationEvent" />
</configure>
@@ -0,0 +1,36 @@
##############################################################################
#
# Copyright (c) 2004 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.
#
##############################################################################
"""Component Architecture-specific event dispatching
Based on subscription adapters / handlers.
"""
from zope.event import subscribers as event_subscribers
from zope.interface.interfaces import IObjectEvent
from zope.component._api import subscribers as component_subscribers
from zope.component._declaration import adapter
def dispatch(*event):
component_subscribers(event, None)
event_subscribers.append(dispatch)
@adapter(IObjectEvent)
def objectEventNotify(event):
"""Dispatch ObjectEvents to interested adapters.
"""
component_subscribers((event.object, event), None)
@@ -0,0 +1,57 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Placeless Test Setup
"""
from zope.component import provideHandler
from zope.component.event import objectEventNotify
from zope.component.registry import dispatchUtilityRegistrationEvent
from zope.component.registry import dispatchAdapterRegistrationEvent
from zope.component.registry import (
dispatchSubscriptionAdapterRegistrationEvent)
from zope.component.registry import dispatchHandlerRegistrationEvent
try:
from zope.testing.cleanup import addCleanUp
except ImportError:
def addCleanUp(x):
pass
events = []
def getEvents(event_type=None, filter=None):
r = []
for event in events:
if event_type is not None and not event_type.providedBy(event):
continue
if filter is not None and not filter(event):
continue
r.append(event)
return r
def clearEvents():
del events[:]
addCleanUp(clearEvents)
class PlacelessSetup:
def setUp(self):
provideHandler(objectEventNotify)
provideHandler(dispatchUtilityRegistrationEvent)
provideHandler(dispatchAdapterRegistrationEvent)
provideHandler(dispatchSubscriptionAdapterRegistrationEvent)
provideHandler(dispatchHandlerRegistrationEvent)
provideHandler(events.append, (None,))
def setUp(test=None):
PlacelessSetup().setUp()
@@ -0,0 +1,47 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Factory object
"""
from zope.interface import implementer
from zope.interface import implementedBy
from zope.interface.declarations import Implements
from zope.component.interfaces import IFactory
@implementer(IFactory)
class Factory(object):
"""Generic factory implementation.
The purpose of this implementation is to provide a quick way of creating
factories for classes, functions and other objects.
"""
def __init__(self, callable, title='', description='', interfaces=None):
self._callable = callable
self.title = title
self.description = description
self._interfaces = interfaces
def __call__(self, *args, **kw):
return self._callable(*args, **kw)
def getInterfaces(self):
if self._interfaces is not None:
spec = Implements(*self._interfaces)
spec.__name__ = getattr(self._callable, '__name__', '[callable]')
return spec
return implementedBy(self._callable)
def __repr__(self): #pragma NO COVER
return '<%s for %s>' % (self.__class__.__name__, repr(self._callable))
@@ -0,0 +1,79 @@
##############################################################################
#
# Copyright (c) 2006 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.
#
##############################################################################
"""Global components support
"""
from zope.interface import implementer
from zope.interface.adapter import AdapterRegistry
from zope.interface.registry import Components
from zope.interface.interfaces import IComponentLookup
def GAR(components, registryName):
return getattr(components, registryName)
class GlobalAdapterRegistry(AdapterRegistry):
"""A global adapter registry
This adapter registry's main purpose is to be picklable in combination
with a site manager."""
def __init__(self, parent, name):
self.__parent__ = parent
self.__name__ = name
super(GlobalAdapterRegistry, self).__init__()
def __reduce__(self):
return GAR, (self.__parent__, self.__name__)
@implementer(IComponentLookup)
class BaseGlobalComponents(Components):
def _init_registries(self):
self.adapters = GlobalAdapterRegistry(self, 'adapters')
self.utilities = GlobalAdapterRegistry(self, 'utilities')
def __reduce__(self):
# Global site managers are pickled as global objects
return self.__name__
base = BaseGlobalComponents('base')
try:
from zope.testing.cleanup import addCleanUp
except ImportError: #pragma NO COVER
pass
else:
addCleanUp(lambda: base.__init__('base'))
del addCleanUp
globalSiteManager = base
def getGlobalSiteManager():
return globalSiteManager
# The following APIs provide global registration support for Python code.
# We eventually want to deprecate these in favor of using the global
# component registry directly.
def provideUtility(component, provides=None, name=u''):
base.registerUtility(component, provides, name, event=False)
def provideAdapter(factory, adapts=None, provides=None, name=u''):
base.registerAdapter(factory, adapts, provides, name, event=False)
def provideSubscriptionAdapter(factory, adapts=None, provides=None):
base.registerSubscriptionAdapter(factory, adapts, provides, event=False)
def provideHandler(factory, adapts=None):
base.registerHandler(factory, adapts, event=False)
@@ -0,0 +1,19 @@
##############################################################################
#
# Copyright (c) 2009 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.
#
##############################################################################
"""
This module is deprecated. Prefer to use zope.hookable.hookable.
"""
# pragma: no cover
import zope.deprecation
zope.deprecation.moved("zope.hookable", "4.5")
@@ -0,0 +1,148 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Hooks for getting and setting a site in the thread global namespace.
"""
__docformat__ = 'restructuredtext'
import contextlib
import threading
try:
from zope.security.proxy import removeSecurityProxy
except ImportError: #pragma NO COVER
def removeSecurityProxy(x):
return x
from zope.component.globalregistry import getGlobalSiteManager
from zope.interface.interfaces import ComponentLookupError
from zope.interface.interfaces import IComponentLookup
class read_property(object):
"""Descriptor for property-like computed attributes.
Unlike the standard 'property', this descriptor allows assigning a
value to the instance, shadowing the property getter function.
"""
def __init__(self, func):
self.func = func
def __get__(self, inst, cls):
if inst is None:
return self
return self.func(inst)
class SiteInfo(threading.local):
site = None
sm = getGlobalSiteManager()
@read_property
def adapter_hook(self):
adapter_hook = self.sm.adapters.adapter_hook
self.adapter_hook = adapter_hook
return adapter_hook
siteinfo = SiteInfo()
def setSite(site=None):
if site is None:
sm = getGlobalSiteManager()
else:
# We remove the security proxy because there's no way for
# untrusted code to get at it without it being proxied again.
# We should really look look at this again though, especially
# once site managers do less. There's probably no good reason why
# they can't be proxied. Well, except maybe for performance.
site = removeSecurityProxy(site)
# The getSiteManager method is defined by IPossibleSite.
sm = site.getSiteManager()
siteinfo.site = site
siteinfo.sm = sm
try:
del siteinfo.adapter_hook
except AttributeError:
pass
def getSite():
return siteinfo.site
@contextlib.contextmanager
def site(site):
old_site = getSite()
setSite(site)
try:
yield
finally:
setSite(old_site)
def getSiteManager(context=None):
"""A special hook for getting the site manager.
Here we take the currently set site into account to find the appropriate
site manager.
"""
if context is None:
return siteinfo.sm
# We remove the security proxy because there's no way for
# untrusted code to get at it without it being proxied again.
# We should really look look at this again though, especially
# once site managers do less. There's probably no good reason why
# they can't be proxied. Well, except maybe for performance.
sm = IComponentLookup(
context, getGlobalSiteManager())
sm = removeSecurityProxy(sm)
return sm
def adapter_hook(interface, object, name='', default=None):
try:
return siteinfo.adapter_hook(interface, object, name, default)
except ComponentLookupError:
return default
def setHooks():
from zope.component import _api
_api.adapter_hook.sethook(adapter_hook)
_api.getSiteManager.sethook(getSiteManager)
def resetHooks():
# Reset hookable functions to original implementation.
from zope.component import _api
_api.adapter_hook.reset()
_api.getSiteManager.reset()
# be sure the old adapter hook isn't cached, since
# it is derived from the SiteManager
try:
del siteinfo.adapter_hook
except AttributeError:
pass
# Clear the site thread global
clearSite = setSite
try:
from zope.testing.cleanup import addCleanUp
except ImportError: #pragma NO COVER
pass
else:
addCleanUp(resetHooks)
@@ -0,0 +1,116 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Interface utility functions
"""
from zope.interface import alsoProvides
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
from zope.interface.interfaces import ComponentLookupError
from zope.component._api import queryUtility
from zope.component._compat import CLASS_TYPES
def provideInterface(id, interface, iface_type=None, info=''):
""" Mark 'interface' as a named utilty providing 'iface_type'.
"""
if not id:
id = "%s.%s" % (interface.__module__, interface.__name__)
if not IInterface.providedBy(interface):
if not isinstance(interface, CLASS_TYPES):
raise TypeError(id, "is not an interface or class")
return
if iface_type is not None:
if not iface_type.extends(IInterface):
raise TypeError(iface_type, "is not an interface type")
alsoProvides(interface, iface_type)
else:
iface_type = IInterface
gsm = getGlobalSiteManager()
gsm.registerUtility(interface, iface_type, id, info)
def getInterface(context, id):
"""Return interface or raise ComponentLookupError
"""
iface = queryInterface(id, None)
if iface is None:
raise ComponentLookupError(id)
return iface
def queryInterface(id, default=None):
"""Return an interface or ``None``
"""
return queryUtility(IInterface, id, default)
def searchInterface(context, search_string=None, base=None):
"""Interfaces search
"""
return [iface_util[1] for iface_util in
searchInterfaceUtilities(context, search_string, base)]
def searchInterfaceIds(context, search_string=None, base=None):
"""Interfaces search
"""
return [iface_util[0] for iface_util in
searchInterfaceUtilities(context, search_string, base)]
def searchInterfaceUtilities(context, search_string=None, base=None):
gsm = getGlobalSiteManager()
iface_utilities = gsm.getUtilitiesFor(IInterface)
if search_string:
search_string = search_string.lower()
iface_utilities = [iface_util for iface_util in iface_utilities
if (getInterfaceAllDocs(iface_util[1]).
find(search_string) >= 0)]
if base:
res = [iface_util for iface_util in iface_utilities
if iface_util[1].isOrExtends(base)]
else:
res = [iface_util for iface_util in iface_utilities]
return res
def getInterfaceAllDocs(interface):
iface_id = '%s.%s' % (interface.__module__, interface.__name__)
docs = [str(iface_id).lower(),
str(interface.__doc__).lower()]
if IInterface.providedBy(interface):
for name in sorted(interface):
docs.append(
str(interface.getDescriptionFor(name).__doc__).lower())
return '\n'.join(docs)
def nameToInterface(context, id):
if id == 'None':
return None
iface = getInterface(context, id)
return iface
def interfaceToName(context, interface):
if interface is None:
return 'None'
return '%s.%s' % (interface.__module__, interface.__name__)
@@ -0,0 +1,437 @@
############################################################################
#
# Copyright (c) 2001, 2002 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.
#
############################################################################
"""Component and Component Architecture Interfaces
"""
from zope.interface import Attribute
from zope.interface import Interface
# BBB 2011-09-09, import interfaces from zope.interface
import zope.deferredimport
zope.deferredimport.deprecatedFrom(
"Import from zope.interface.interfaces",
"zope.interface.interfaces",
'ComponentLookupError',
'Invalid',
'IObjectEvent',
'ObjectEvent',
'IComponentLookup',
'IRegistration',
'IUtilityRegistration',
'_IBaseAdapterRegistration',
'IAdapterRegistration',
'ISubscriptionAdapterRegistration',
'IHandlerRegistration',
'IRegistrationEvent',
'RegistrationEvent',
'IRegistered',
'Registered',
'IUnregistered',
'Unregistered',
'IComponentRegistry',
'IComponents',
)
class IComponentArchitecture(Interface):
"""The Component Architecture is defined by two key components: Adapters
and Utiltities. Both are managed by site managers. All other components
build on top of them.
"""
# Site Manager API
def getGlobalSiteManager():
"""Return the global site manager.
This function should never fail and always return an object that
provides `IGlobalSiteManager`.
"""
def getSiteManager(context=None):
"""Get the nearest site manager in the given context.
If `context` is `None`, return the global site manager.
If the `context` is not `None`, it is expected that an adapter
from the `context` to `IComponentLookup` can be found. If no
adapter is found, a `ComponentLookupError` is raised.
"""
# Utility API
def getUtility(interface, name='', context=None):
"""Get the utility that provides interface
Returns the nearest utility to the context that implements the
specified interface. If one is not found, raises
ComponentLookupError.
"""
def queryUtility(interface, name='', default=None, context=None):
"""Look for the utility that provides interface
Returns the nearest utility to the context that implements
the specified interface. If one is not found, returns default.
"""
def queryNextUtility(context, interface, name='', default=None):
"""Query for the next available utility.
Find the next available utility providing `interface` and having the
specified name. If no utility was found, return the specified `default`
value.
"""
def getNextUtility(context, interface, name=''):
"""Get the next available utility.
If no utility was found, a `ComponentLookupError` is raised.
"""
def getUtilitiesFor(interface, context=None):
"""Return the utilities that provide an interface
An iterable of utility name-value pairs is returned.
"""
def getAllUtilitiesRegisteredFor(interface, context=None):
"""Return all registered utilities for an interface
This includes overridden utilities.
An iterable of utility instances is returned. No names are
returned.
"""
# Adapter API
def getAdapter(object,
interface=Interface, name=u'',
context=None):
"""Get a named adapter to an interface for an object
Returns an adapter that can adapt object to interface. If a matching
adapter cannot be found, raises ComponentLookupError.
If context is None, an application-defined policy is used to choose
an appropriate service manager from which to get an 'Adapters' service.
If 'context' is not None, context is adapted to IServiceService,
and this adapter's 'Adapters' service is used.
"""
def getAdapterInContext(object, interface, context):
"""Get a special adapter to an interface for an object
NOTE: This method should only be used if a custom context
needs to be provided to provide custom component
lookup. Otherwise, call the interface, as in::
interface(object)
Returns an adapter that can adapt object to interface. If a matching
adapter cannot be found, raises ComponentLookupError.
Context is adapted to IServiceService, and this adapter's
'Adapters' service is used.
If the object has a __conform__ method, this method will be
called with the requested interface. If the method returns a
non-None value, that value will be returned. Otherwise, if the
object already implements the interface, the object will be
returned.
"""
def getMultiAdapter(objects,
interface=Interface, name='',
context=None):
"""Look for a multi-adapter to an interface for an objects
Returns a multi-adapter that can adapt objects to interface. If a
matching adapter cannot be found, raises ComponentLookupError.
If context is None, an application-defined policy is used to choose
an appropriate service manager from which to get an 'Adapters' service.
If 'context' is not None, context is adapted to IServiceService,
and this adapter's 'Adapters' service is used.
The name consisting of an empty string is reserved for unnamed
adapters. The unnamed adapter methods will often call the
named adapter methods with an empty string for a name.
"""
def queryAdapter(object, interface=Interface, name=u'',
default=None, context=None):
"""Look for a named adapter to an interface for an object
Returns an adapter that can adapt object to interface. If a matching
adapter cannot be found, returns the default.
If context is None, an application-defined policy is used to choose
an appropriate service manager from which to get an 'Adapters' service.
If 'context' is not None, context is adapted to IServiceService,
and this adapter's 'Adapters' service is used.
"""
def queryAdapterInContext(object, interface, context, default=None):
"""Look for a special adapter to an interface for an object
NOTE: This method should only be used if a custom context
needs to be provided to provide custom component
lookup. Otherwise, call the interface, as in::
interface(object, default)
Returns an adapter that can adapt object to interface. If a matching
adapter cannot be found, returns the default.
Context is adapted to IServiceService, and this adapter's
'Adapters' service is used.
If the object has a __conform__ method, this method will be
called with the requested interface. If the method returns a
non-None value, that value will be returned. Otherwise, if the
object already implements the interface, the object will be
returned.
"""
def queryMultiAdapter(objects,
interface=Interface, name=u'',
default=None,
context=None):
"""Look for a multi-adapter to an interface for objects
Returns a multi-adapter that can adapt objects to interface. If a
matching adapter cannot be found, returns the default.
If context is None, an application-defined policy is used to choose
an appropriate service manager from which to get an 'Adapters' service.
If 'context' is not None, context is adapted to IServiceService,
and this adapter's 'Adapters' service is used.
The name consisting of an empty string is reserved for unnamed
adapters. The unnamed adapter methods will often call the
named adapter methods with an empty string for a name.
"""
def getAdapters(objects, provided, context=None):
"""Look for all matching adapters to a provided interface for objects
Return a list of adapters that match. If an adapter is named, only the
most specific adapter of a given name is returned.
If context is None, an application-defined policy is used to choose
an appropriate service manager from which to get an 'Adapters'
service.
If 'context' is not None, context is adapted to IServiceService,
and this adapter's 'Adapters' service is used.
"""
def subscribers(required, provided, context=None):
"""Get subscribers
Subscribers are returned that provide the provided interface
and that depend on and are computed from the sequence of
required objects.
If context is None, an application-defined policy is used to choose
an appropriate service manager from which to get an 'Adapters'
service.
If 'context' is not None, context is adapted to IServiceService,
and this adapter's 'Adapters' service is used.
"""
def handle(*objects):
"""Call all of the handlers for the given objects
Handlers are subscription adapter factories that don't produce
anything. They do all of their work when called. Handlers
are typically used to handle events.
"""
def adapts(*interfaces):
"""Declare that a class adapts the given interfaces.
This function can only be used in a class definition.
(TODO, allow classes to be passed as well as interfaces.)
"""
# Factory service
def createObject(factory_name, *args, **kwargs):
"""Create an object using a factory
Finds the named factory in the current site and calls it with
the given arguments. If a matching factory cannot be found
raises ComponentLookupError. Returns the created object.
A context keyword argument can be provided to cause the
factory to be looked up in a location other than the current
site. (Of course, this means that it is impossible to pass a
keyword argument named "context" to the factory.
"""
def getFactoryInterfaces(name, context=None):
"""Get interfaces implemented by a factory
Finds the factory of the given name that is nearest to the
context, and returns the interface or interface tuple that
object instances created by the named factory will implement.
"""
def getFactoriesFor(interface, context=None):
"""Return a tuple (name, factory) of registered factories that
create objects which implement the given interface.
"""
class IRegistry(Interface):
"""Object that supports component registry
"""
def registrations():
"""Return an iterable of component registrations
"""
class IComponentRegistrationConvenience(Interface):
"""API for registering components.
CAUTION: This API should only be used from test or
application-setup code. This api shouldn't be used by regular
library modules, as component registration is a configuration
activity.
"""
def provideUtility(component, provides=None, name=u''):
"""Register a utility globally
A utility is registered to provide an interface with a
name. If a component provides only one interface, then the
provides argument can be omitted and the provided interface
will be used. (In this case, provides argument can still be
provided to provide a less specific interface.)
CAUTION: This API should only be used from test or
application-setup code. This API shouldn't be used by regular
library modules, as component registration is a configuration
activity.
"""
def provideAdapter(factory, adapts=None, provides=None, name=u''):
"""Register an adapter globally
An adapter is registered to provide an interface with a name
for some number of object types. If a factory implements only
one interface, then the provides argument can be omitted and
the provided interface will be used. (In this case, a provides
argument can still be provided to provide a less specific
interface.)
If the factory has an adapts declaration, then the adapts
argument can be omitted and the declaration will be used. (An
adapts argument can be provided to override the declaration.)
CAUTION: This API should only be used from test or
application-setup code. This API shouldn't be used by regular
library modules, as component registration is a configuration
activity.
"""
def provideSubscriptionAdapter(factory, adapts=None, provides=None):
"""Register a subscription adapter
A subscription adapter is registered to provide an interface
for some number of object types. If a factory implements only
one interface, then the provides argument can be omitted and
the provided interface will be used. (In this case, a provides
argument can still be provided to provide a less specific
interface.)
If the factory has an adapts declaration, then the adapts
argument can be omitted and the declaration will be used. (An
adapts argument can be provided to override the declaration.)
CAUTION: This API should only be used from test or
application-setup code. This API shouldn't be used by regular
library modules, as component registration is a configuration
activity.
"""
def provideHandler(handler, adapts=None):
"""Register a handler
Handlers are subscription adapter factories that don't produce
anything. They do all of their work when called. Handlers
are typically used to handle events.
If the handler has an adapts declaration, then the adapts
argument can be omitted and the declaration will be used. (An
adapts argument can be provided to override the declaration.)
CAUTION: This API should only be used from test or
application-setup code. This API shouldn't be used by regular
library modules, as component registration is a configuration
activity.
"""
class IPossibleSite(Interface):
"""An object that could be a site.
"""
def setSiteManager(sitemanager):
"""Sets the site manager for this object.
"""
def getSiteManager():
"""Returns the site manager contained in this object.
If there isn't a site manager, raise a component lookup.
"""
class ISite(IPossibleSite):
"""Marker interface to indicate that we have a site"""
class Misused(Exception):
"""A component is being used (registered) for the wrong interface."""
class IFactory(Interface):
"""A factory is responsible for creating other components."""
title = Attribute("The factory title.")
description = Attribute("A brief description of the factory.")
def __call__(*args, **kw):
"""Return an instance of the objects we're a factory for."""
def getInterfaces():
"""Get the interfaces implemented by the factory
Return the interface(s), as an instance of Implements, that objects
created by this factory will implement. If the callable's Implements
instance cannot be created, an empty Implements instance is returned.
"""
@@ -0,0 +1,45 @@
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:meta="http://namespaces.zope.org/meta">
<meta:directives namespace="http://namespaces.zope.org/zope">
<meta:directive
name="interface"
schema="zope.component.zcml.IInterfaceDirective"
handler="zope.component.zcml.interface"
/>
<meta:directive
name="adapter"
schema="zope.component.zcml.IAdapterDirective"
handler="zope.component.zcml.adapter"
/>
<meta:directive
name="subscriber"
schema="zope.component.zcml.ISubscriberDirective"
handler="zope.component.zcml.subscriber"
/>
<meta:directive
name="utility"
schema="zope.component.zcml.IUtilityDirective"
handler="zope.component.zcml.utility"
/>
<meta:directive
name="view"
schema="zope.component.zcml.IViewDirective"
handler="zope.component.zcml.view"
/>
<meta:directive
name="resource"
schema="zope.component.zcml.IResourceDirective"
handler="zope.component.zcml.resource"
/>
</meta:directives>
</configure>
@@ -0,0 +1,54 @@
##############################################################################
#
# Copyright (c) 2004 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.
#
##############################################################################
"""Persistent component managers
"""
from persistent import Persistent
from persistent.mapping import PersistentMapping
from persistent.list import PersistentList
from zope.interface.adapter import VerifyingAdapterRegistry
from zope.interface.registry import Components
class PersistentAdapterRegistry(VerifyingAdapterRegistry, Persistent):
def changed(self, originally_changed):
if originally_changed is self:
self._p_changed = True
super(PersistentAdapterRegistry, self).changed(originally_changed)
def __getstate__(self):
state = super(PersistentAdapterRegistry, self).__getstate__().copy()
for name in self._delegated:
state.pop(name, 0)
state.pop('ro', None)
return state
def __setstate__(self, state):
bases = state.pop('__bases__', ())
super(PersistentAdapterRegistry, self).__setstate__(state)
self._createLookup()
self.__bases__ = bases
self._v_lookup.changed(self)
class PersistentComponents(Components):
def _init_registries(self):
self.adapters = PersistentAdapterRegistry()
self.utilities = PersistentAdapterRegistry()
def _init_registrations(self):
self._utility_registrations = PersistentMapping()
self._adapter_registrations = PersistentMapping()
self._subscription_registrations = PersistentList()
self._handler_registrations = PersistentList()
@@ -0,0 +1,56 @@
##############################################################################
#
# Copyright (c) 2006 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.
#
##############################################################################
"""Basic components support
"""
from zope.component._api import handle
from zope.component._declaration import adapter
from zope.interface.interfaces import IAdapterRegistration
from zope.interface.interfaces import IHandlerRegistration
from zope.interface.interfaces import IRegistrationEvent
from zope.interface.interfaces import ISubscriptionAdapterRegistration
from zope.interface.interfaces import IUtilityRegistration
# BBB, import component-related from zope.interface
import zope.deferredimport
zope.deferredimport.deprecatedFrom(
"Import from zope.interface.registry",
"zope.interface.registry",
'Components',
'_getUtilityProvided',
'_getAdapterProvided',
'_getAdapterRequired',
'UtilityRegistration',
'AdapterRegistration',
'SubscriptionRegistration',
'HandlerRegistration',
)
@adapter(IUtilityRegistration, IRegistrationEvent)
def dispatchUtilityRegistrationEvent(registration, event):
handle(registration.component, event)
@adapter(IAdapterRegistration, IRegistrationEvent)
def dispatchAdapterRegistrationEvent(registration, event):
handle(registration.factory, event)
@adapter(ISubscriptionAdapterRegistration, IRegistrationEvent)
def dispatchSubscriptionAdapterRegistrationEvent(registration, event):
handle(registration.factory, event)
@adapter(IHandlerRegistration, IRegistrationEvent)
def dispatchHandlerRegistrationEvent(registration, event):
handle(registration.handler, event)
@@ -0,0 +1,100 @@
##############################################################################
#
# 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.
#
##############################################################################
"""zope.security support for the configuration handlers
"""
from zope.interface import providedBy
from zope.proxy import ProxyBase
from zope.proxy import getProxiedObject
from zope.security.adapter import LocatingTrustedAdapterFactory
from zope.security.adapter import LocatingUntrustedAdapterFactory
from zope.security.adapter import TrustedAdapterFactory
from zope.security.checker import Checker
from zope.security.checker import CheckerPublic
from zope.security.checker import InterfaceChecker
from zope.security.proxy import Proxy
PublicPermission = 'zope.Public'
class PermissionProxy(ProxyBase):
__slots__ = ('__Security_checker__', )
def __providedBy__(self):
return providedBy(getProxiedObject(self))
__providedBy__ = property(__providedBy__)
def _checker(_context, permission, allowed_interface, allowed_attributes):
if (not allowed_attributes) and (not allowed_interface):
allowed_attributes = ["__call__"]
if permission == PublicPermission:
permission = CheckerPublic
require={}
if allowed_attributes:
for name in allowed_attributes:
require[name] = permission
if allowed_interface:
for i in allowed_interface:
for name in i.names(all=True):
require[name] = permission
checker = Checker(require)
return checker
def proxify(ob, checker=None, provides=None, permission=None):
"""Try to get the object proxied with the `checker`, but not too soon
We really don't want to proxy the object unless we need to.
"""
if checker is None:
if provides is None or permission is None:
raise ValueError('Required arguments: '
'checker or both provides and permissions')
if permission == PublicPermission:
permission = CheckerPublic
checker = InterfaceChecker(provides, permission)
ob = PermissionProxy(ob)
ob.__Security_checker__ = checker
return ob
def protectedFactory(original_factory, provides, permission):
if permission == PublicPermission:
permission = CheckerPublic
checker = InterfaceChecker(provides, permission)
# This has to be named 'factory', aparently, so as not to confuse apidoc :(
def factory(*args):
ob = original_factory(*args)
try:
ob.__Security_checker__ = checker
except AttributeError:
ob = Proxy(ob, checker)
return ob
factory.factory = original_factory
return factory
def securityAdapterFactory(factory, permission, locate, trusted):
if permission == PublicPermission:
permission = CheckerPublic
if locate or (permission is not None and permission is not CheckerPublic):
if trusted:
return LocatingTrustedAdapterFactory(factory)
else:
return LocatingUntrustedAdapterFactory(factory)
elif trusted:
return TrustedAdapterFactory(factory)
else:
return factory
@@ -0,0 +1,55 @@
"""
See: https://bugs.launchpad.net/zope3/+bug/98401
"""
import sys
import pickle
def write(x):
sys.stdout.write('%s\n' % x)
if __name__ == "__main__":
if sys.version_info[0] >= 3:
# TextIO? Are you kidding me?
data = sys.stdin.buffer.read()
else:
data = sys.stdin.read()
sys.path = pickle.loads(data)
write('XXXXXXXXXX')
for p in sys.path:
write('- %s' % p)
write('XXXXXXXXXX')
import zope
from zope.interface import Interface
from zope.interface import implementer
class I1(Interface):
pass
class I2(Interface):
pass
@implementer(I1)
class Ob(object):
def __repr__(self):
return '<instance Ob>'
ob = Ob()
@implementer(I2)
class Comp(object):
def __init__(self, context):
self.context = context
write('YYYYYYYYY')
for p in zope.__path__:
write('- %s' % p)
write('YYYYYYYYY')
import zope.component
zope.component.provideAdapter(Comp, (I1,), I2)
adapter = I2(ob)
write('ZZZZZZZZ')
assert adapter.__class__ is Comp
assert adapter.context is ob
@@ -0,0 +1 @@
#Python package
@@ -0,0 +1,68 @@
##############################################################################
#
# Copyright (c) 2004 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.
#
##############################################################################
"""Sample adapter class for testing
"""
from zope.interface import Interface
from zope.interface import implementer
from zope.component import adapter
from zope.component.testfiles import components
class I1(Interface):
pass
class I2(Interface):
pass
class I3(Interface):
def f1(): pass
def f2(): pass
def f3(): pass
class IS(Interface):
pass
class Adapter(object):
def __init__(self, *args):
self.context = args
@implementer(I1)
class A1(Adapter):
pass
@implementer(I2)
class A2(Adapter):
pass
@adapter(components.IContent, I1, I2)
@implementer(I3)
class A3(Adapter):
pass
class A4:
pass
a4 = A4()
@implementer(I1, I2)
class A5:
pass
a5 = A5()
def Handler(content, *args):
# uninteresting handler
content.args = getattr(content, 'args', ()) + (args, )
@@ -0,0 +1,66 @@
##############################################################################
#
# Copyright (c) 2002 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.
#
##############################################################################
"""Components for testing
"""
from zope.interface import Interface
from zope.interface import Attribute
from zope.interface import implementer
from zope.component import adapter
from zope.component import named
class IAppb(Interface):
a = Attribute('test attribute')
def f(): "test func"
class IApp(IAppb):
pass
class IApp2(IAppb):
pass
class IApp3(IAppb):
pass
class IContent(Interface): pass
@implementer(IContent)
class Content(object):
pass
@adapter(IContent)
@implementer(IApp)
class Comp(object):
def __init__(self, *args):
# Ignore arguments passed to constructor
pass
a = 1
def f(): pass
class Comp2(object):
def __init__(self, context):
self.context = context
@adapter(IContent)
@implementer(IApp)
@named('app')
class Comp4(object):
def __init__(self, context=None):
self.context = context
comp = Comp()
comp4 = Comp4()
content = Content()
@@ -0,0 +1,9 @@
<configure xmlns="http://namespaces.zope.org/zope">
<include package="zope.component" file="meta.zcml" />
<adapter
factory="zope.component.testfiles.components.Comp2"
provides="zope.component.testfiles.components.IApp2"
for="zope.component.testfiles.components.IContent" />
</configure>
@@ -0,0 +1,20 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Views test.
"""
from zope.interface import Interface
class IC(Interface):
pass
@@ -0,0 +1,37 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Placeless Test Setup
"""
# HACK to make sure basicmost event subscriber is installed
import zope.component.event
# we really don't need special setup now:
class _PlacelessSetupFallback(object):
def cleanUp(self):
from zope.component.globalregistry import base
base.__init__('base')
setUp = tearDown = cleanUp
try:
from zope.testing.cleanup import CleanUp as PlacelessSetup
except ImportError: # pragma: no cover
PlacelessSetup = _PlacelessSetupFallback
def setUp(test=None):
PlacelessSetup().setUp()
def tearDown(test=None):
PlacelessSetup().tearDown()
@@ -0,0 +1,120 @@
##############################################################################
#
# Copyright (c) 2010 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.
#
##############################################################################
import os
from zope.configuration import xmlconfig, config
try:
from zope.testing.cleanup import cleanUp
except ImportError: # pragma: no cover
def cleanUp():
pass
from zope.component import provideHandler
from zope.component.hooks import setHooks
from zope.component.eventtesting import events, clearEvents
class LayerBase(object):
"""Sane layer base class.
zope.testing implements an advanced mechanism so that layer setUp,
tearDown, testSetUp and testTearDown code gets called in the right
order. These methods are supposed to be @classmethods and should
not use super() as the test runner is supposed to take care of that.
In practice, this mechanism turns out not to be useful and
overcomplicated. It becomes difficult to pass information into
layers (such as a ZCML file to load), because the only way to pass
in information is to subclass, and subclassing these layers leads
to a range of interactions that is hard to reason about.
We'd rather just use Python and the super mechanism, as we know how
to reason about that. This base class is a hack to make this
possible.
The hack requires us to set __bases__, __module__ and
__name__. This fools zope.testing into thinking that this layer
instance is a class it can work with.
It'd be better if zope.testing just called a minimal API and
didn't try to be fancy. Fancy layer inheritance mechanisms can
then be implemented elsewhere if people want to. But unfortunately
it does implement a fancy mechanism and we need to fool it.
"""
__bases__ = ()
def __init__(self, package, name=None):
if name is None:
name = self.__class__.__name__
self.__name__ = name
self.__module__ = package.__name__
self.package = package
def setUp(self):
pass
def tearDown(self):
pass
def testSetUp(self):
pass
def testTearDown(self):
pass
class ZCMLLayerBase(LayerBase):
"""Base class to load up some ZCML.
"""
def __init__(self, package, name=None, features=None):
super(ZCMLLayerBase, self).__init__(package, name)
self.features = features or []
def setUp(self):
setHooks()
context = config.ConfigurationMachine()
xmlconfig.registerCommonDirectives(context)
for feature in self.features:
context.provideFeature(feature)
self.context = self._load_zcml(context)
provideHandler(events.append, (None,))
def testTearDown(self):
clearEvents()
def tearDown(self):
cleanUp()
def _load_zcml(self, context):
raise NotImplementedError
class ZCMLFileLayer(ZCMLLayerBase):
"""This layer can be used to run tests with a ZCML file loaded.
The ZCML file is assumed to include sufficient (meta)configuration
so that it can be interpreted itself. I.e. to create a ZCMLLayer
based on another ZCMLLayer's ZCML, just use a ZCML include
statement in your own ZCML to load it.
"""
def __init__(self, package, zcml_file='ftesting.zcml',
name=None, features=None):
super(ZCMLFileLayer, self).__init__(package, name, features)
self.zcml_file = os.path.join(os.path.dirname(package.__file__),
zcml_file)
def _load_zcml(self, context):
return xmlconfig.file(self.zcml_file,
package=self.package,
context=context, execute=True)
@@ -0,0 +1,23 @@
import unittest
def skipIfNoSecurity(testfunc):
try:
import zope.security
except ImportError: # pragma: no cover
return unittest.skip("zope.security not installed")(testfunc)
return testfunc
def fails_if_called(test, msg="This function must not be called.",
arguments=True):
"""
Return a new function (accepting any arguments)
that will call test.fail(msg) if it is called.
:keyword bool arguments: If set to ``False``, then we will
not accept any arguments. This can avoid
masking when we would expect a TypeError to be raised by
calling an instance method against a class.
"""
if not arguments:
return lambda: test.fail(msg)
return lambda *_args, **__kwargs: test.fail(msg)
@@ -0,0 +1,142 @@
##############################################################################
#
# Copyright (c) 2001, 2002, 2009 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.
#
##############################################################################
"""Examples supporting Sphinx doctest snippets.
"""
import sys
from zope.interface import Interface
from zope.interface import implementer
from zope.interface.interfaces import IInterface
from zope.component._declaration import adapter
from zope.component.testfiles.views import IC
def write(x):
sys.stdout.write('%s\n' % x)
class ITestType(IInterface):
pass
class I1(Interface):
pass
class I2(Interface):
pass
class I3(Interface):
pass
class I4(Interface):
pass
class IGI(Interface):
pass
class IQI(Interface):
pass
class ISI(Interface):
pass
class ISII(Interface):
pass
class U(object):
def __init__(self, name):
self.__name__ = name
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__, self.__name__)
@implementer(I1)
class U1(U):
pass
@implementer(I1, I2)
class U12(U):
pass
@adapter(I1)
def handle1(x):
write('handle1 %s' % x)
def handle2(*objects):
write( 'handle2 ' + repr(objects))
@adapter(I1)
def handle3(x):
write( 'handle3 %s' % x)
@adapter(I1)
def handle4(x):
write( 'handle4 %s' % x)
class GlobalRegistry:
pass
from zope.component.globalregistry import GlobalAdapterRegistry
base = GlobalAdapterRegistry(GlobalRegistry, 'adapters')
GlobalRegistry.adapters = base
def clear_base():
base.__init__(GlobalRegistry, 'adapters')
@implementer(I1)
class Ob(object):
def __repr__(self):
return '<instance Ob>'
ob = Ob()
@implementer(I2)
class Ob2(object):
def __repr__(self):
return '<instance Ob2>'
@implementer(IC)
class Ob3(object):
pass
@implementer(I2)
class Comp(object):
def __init__(self, context):
self.context = context
comp = Comp(1)
class ConformsToIComponentLookup(object):
"""Allow a dummy sitemanager to conform/adapt to `IComponentLookup`."""
def __init__(self, sitemanager):
self.sitemanager = sitemanager
def __conform__(self, interface):
"""This method is specified by the adapter PEP to do the adaptation."""
from zope.interface.interfaces import IComponentLookup
if interface is IComponentLookup:
return self.sitemanager
def clearZCML(test=None):
from zope.configuration.xmlconfig import XMLConfig
import zope.component
from zope.component.testing import setUp
from zope.component.testing import tearDown
tearDown()
setUp()
XMLConfig('meta.zcml', zope.component)()
@@ -0,0 +1,92 @@
##############################################################################
#
# Copyright (c) 2012 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.
#
##############################################################################
import unittest
class Test_package(unittest.TestCase):
def test_module_conforms_to_IComponentArchitecture(self):
from zope.interface.verify import verifyObject
from zope.component.interfaces import IComponentArchitecture
import zope.component as zc
verifyObject(IComponentArchitecture, zc)
def test_module_conforms_to_IComponentRegistrationConvenience(self):
from zope.interface.verify import verifyObject
from zope.component.interfaces import IComponentRegistrationConvenience
import zope.component as zc
verifyObject(IComponentRegistrationConvenience, zc)
class Test_Interface_call(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def test_miss(self):
from zope.interface import Interface
class IFoo(Interface):
pass
self.assertRaises(TypeError, IFoo, object())
def test_miss_w_default(self):
from zope.interface import Interface
class IFoo(Interface):
pass
marker = object()
self.assertTrue(IFoo(object(), marker) is marker)
def test_hit(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.component import getGlobalSiteManager
class IFoo(Interface):
pass
class IBar(Interface):
pass
@implementer(IBar)
class Bar(object):
pass
@implementer(IFoo)
class Baz(object):
def __init__(self, context):
self.context = context
getGlobalSiteManager().registerAdapter(Baz, (IBar,), IFoo, '')
bar = Bar()
adapted = IFoo(bar)
self.assertTrue(adapted.__class__ is Baz)
self.assertTrue(adapted.context is bar)
def test_hit_registered_for_None(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.component import getGlobalSiteManager
class IFoo(Interface):
pass
@implementer(IFoo)
class Baz(object):
def __init__(self, context):
self.context = context
getGlobalSiteManager().registerAdapter(Baz, (None,), IFoo, '')
ctx = object()
adapted = IFoo(ctx)
self.assertTrue(adapted.__class__ is Baz)
self.assertTrue(adapted.context is ctx)
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(Test_package),
unittest.makeSuite(Test_Interface_call),
))
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,196 @@
##############################################################################
#
# Copyright (c) 2012 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.
#
##############################################################################
"""Test adapter declaration helpers
"""
import unittest
class Test_adapter(unittest.TestCase):
def _getTargetClass(self):
from zope.component._declaration import adapter
return adapter
def _makeOne(self, *interfaces):
return self._getTargetClass()(*interfaces)
def test_ctor_no_interfaces(self):
deco = self._makeOne()
self.assertEqual(list(deco.interfaces), [])
def test_ctor_w_interfaces(self):
from zope.interface import Interface
class IFoo(Interface):
pass
class IBar(Interface):
pass
deco = self._makeOne(IFoo, IBar)
self.assertEqual(list(deco.interfaces), [IFoo, IBar])
def test__call___w_class(self):
from zope.interface import Interface
class IFoo(Interface):
pass
class IBar(Interface):
pass
@self._makeOne(IFoo, IBar)
class Baz(object):
pass
self.assertEqual(Baz.__component_adapts__, (IFoo, IBar))
def test__call___w_inst_of_decorated_class(self):
from zope.interface import Interface
class IFoo(Interface):
pass
class IBar(Interface):
pass
@self._makeOne(IFoo, IBar)
class Baz(object):
pass
baz = Baz()
self.assertRaises(AttributeError,
getattr, baz, '__component_adapts_')
def test__call___w_non_class(self):
from zope.interface import Interface
class IFoo(Interface):
pass
class IBar(Interface):
pass
class Baz(object):
pass
deco = self._makeOne(IFoo, IBar)
baz = deco(Baz())
self.assertEqual(baz.__component_adapts__, (IFoo, IBar))
class Test_adapts(unittest.TestCase):
def _run_generated_code(self, code, globs, locs):
import warnings
with warnings.catch_warnings(record=True) as log:
warnings.resetwarnings()
exec(code, globs, locs)
self.assertEqual(len(log), 0) # no longer warn
return True
def test_instances_not_affected(self):
from zope.component._declaration import adapts
class C(object):
adapts()
self.assertEqual(C.__component_adapts__, ())
def _try():
return C().__component_adapts__
self.assertRaises(AttributeError, _try)
def test_called_from_function(self):
import warnings
from zope.component._declaration import adapts
from zope.interface import Interface
class IFoo(Interface):
pass
globs = {'adapts': adapts, 'IFoo': IFoo}
locs = {}
CODE = "\n".join([
'def foo():',
' adapts(IFoo)'
])
self._run_generated_code(CODE, globs, locs)
foo = locs['foo']
with warnings.catch_warnings(record=True) as log:
warnings.resetwarnings()
self.assertRaises(TypeError, foo)
self.assertEqual(len(log), 0) # no longer warn
def test_called_twice_from_class(self):
import warnings
from zope.component._declaration import adapts
from zope.interface import Interface
from zope.interface._compat import PYTHON3
class IFoo(Interface):
pass
class IBar(Interface):
pass
globs = {'adapts': adapts, 'IFoo': IFoo, 'IBar': IBar}
locs = {}
CODE = "\n".join([
'class Foo(object):',
' adapts(IFoo)',
' adapts(IBar)',
])
with warnings.catch_warnings(record=True) as log:
warnings.resetwarnings()
with self.assertRaises(TypeError):
exec(CODE, globs, locs)
self.assertEqual(len(log), 0) # no longer warn
def test_called_once_from_class(self):
from zope.component._declaration import adapts
from zope.interface import Interface
class IFoo(Interface):
pass
globs = {'adapts': adapts, 'IFoo': IFoo}
locs = {}
CODE = "\n".join([
'class Foo(object):',
' adapts(IFoo)',
])
self._run_generated_code(CODE, globs, locs)
Foo = locs['Foo']
spec = Foo.__component_adapts__
self.assertEqual(list(spec), [IFoo])
class Test_adaptedBy(unittest.TestCase):
def _callFUT(self, obj):
from zope.component._declaration import adaptedBy
return adaptedBy(obj)
def test_obj_w_no_attr(self):
self.assertEqual(self._callFUT(object()), None)
def test__call___w_class(self):
from zope.interface import Interface
class IFoo(Interface):
pass
class IBar(Interface):
pass
class Baz(object):
__component_adapts__ = (IFoo, IBar)
self.assertEqual(self._callFUT(Baz), (IFoo, IBar))
def test__call___w_inst_of_decorated_class(self):
from zope.interface import Interface
from zope.component._declaration import _adapts_descr
class IFoo(Interface):
pass
class IBar(Interface):
pass
class Baz(object):
__component_adapts__ = _adapts_descr((IFoo, IBar))
baz = Baz()
self.assertEqual(self._callFUT(baz), None)
def test__call___w_non_class(self):
from zope.interface import Interface
class IFoo(Interface):
pass
class IBar(Interface):
pass
class Baz(object):
pass
baz = Baz()
baz.__component_adapts__ = (IFoo, IBar)
self.assertEqual(self._callFUT(baz), (IFoo, IBar))
@@ -0,0 +1,65 @@
##############################################################################
#
# Copyright (c) 2012 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.
#
##############################################################################
"""Test adapter declaration helpers
"""
import unittest
class Test_dispatch(unittest.TestCase):
def test_it(self):
from zope.interface import Interface
from zope.component.globalregistry import getGlobalSiteManager
from zope.component.event import dispatch
_adapted = []
def _adapter(context):
_adapted.append(context)
return object()
gsm = getGlobalSiteManager()
gsm.registerHandler(_adapter, (Interface,))
del _adapted[:] # clear handler reg
event = object()
dispatch(event)
self.assertEqual(_adapted, [event])
class Test_objectEventNotify(unittest.TestCase):
def test_it(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.component.globalregistry import getGlobalSiteManager
from zope.interface.interfaces import IObjectEvent
from zope.component.event import objectEventNotify
_adapted = []
def _adapter(context, event):
_adapted.append((context, event))
return object()
gsm = getGlobalSiteManager()
gsm.registerHandler(_adapter, (Interface, IObjectEvent))
del _adapted[:] # clear handler reg
@implementer(IObjectEvent)
class _ObjectEvent(object):
def __init__(self, object):
self.object = object
context = object()
event = _ObjectEvent(context)
objectEventNotify(event)
self.assertEqual(_adapted, [(context, event)])
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(Test_dispatch),
unittest.makeSuite(Test_objectEventNotify),
))
@@ -0,0 +1,103 @@
##############################################################################
#
# Copyright (c) 2012 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.
#
##############################################################################
"""Tests for z.c.factory
"""
import unittest
from zope.component.tests import fails_if_called
class FactoryTests(unittest.TestCase):
def _getTargetClass(self):
from zope.component.factory import Factory
return Factory
def _makeOne(self, callable=None, *args, **kw):
if callable is None:
callable = fails_if_called(self)
return self._getTargetClass()(callable, *args, **kw)
def test_class_conforms_to_IFactory(self):
from zope.interface.verify import verifyClass
from zope.component.interfaces import IFactory
verifyClass(IFactory, self._getTargetClass())
def test_instance_conforms_to_IFactory(self):
from zope.interface.verify import verifyObject
from zope.component.interfaces import IFactory
verifyObject(IFactory, self._makeOne())
def test_ctor_defaults(self):
func = fails_if_called(self)
factory = self._makeOne(func)
self.assertEqual(factory._callable, func)
self.assertEqual(factory.title, '')
self.assertEqual(factory.description, '')
self.assertEqual(factory._interfaces, None)
def test_ctor_expclit(self):
factory = self._makeOne(fails_if_called(self), 'TITLE', 'DESCRIPTION')
self.assertEqual(factory.title, 'TITLE')
self.assertEqual(factory.description, 'DESCRIPTION')
def test___call___no_args(self):
_called = []
def _callable(*args, **kw):
_called.append((args, kw))
factory = self._makeOne(_callable)
factory()
self.assertEqual(_called, [((), {})])
def test___call___positional_args(self):
_called = []
def _callable(*args, **kw):
_called.append((args, kw))
factory = self._makeOne(_callable)
factory('one', 'two')
self.assertEqual(_called, [(('one', 'two'), {})])
def test___call___keyword_args(self):
_called = []
def _callable(*args, **kw):
_called.append((args, kw))
factory = self._makeOne(_callable)
factory(foo='bar')
self.assertEqual(_called, [((), {'foo': 'bar'})])
def test_getInterfaces_explicit(self):
from zope.interface import Interface
from zope.interface import implementer
class IFoo(Interface):
pass
class IBar(Interface):
pass
class IBaz(Interface):
pass
_callable = fails_if_called(self)
_callable.__name__ = '_callable'
_callable = implementer(IBaz)(_callable)
factory = self._makeOne(_callable, interfaces=(IFoo, IBar))
spec = factory.getInterfaces()
self.assertEqual(spec.__name__, '_callable')
self.assertEqual(list(spec), [IFoo, IBar])
def test_getInterfaces_implicit(self):
from zope.interface import Interface
from zope.interface import implementer
class IBaz(Interface):
pass
_callable = implementer(IBaz)(fails_if_called(self))
factory = self._makeOne(_callable)
spec = factory.getInterfaces()
self.assertEqual(list(spec), [IBaz])
@@ -0,0 +1,246 @@
##############################################################################
#
# Copyright (c) 2012 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.
#
##############################################################################
""" Tests for z.c._api
"""
import unittest
from zope.component.tests import fails_if_called
class Test_getGlobalSiteManager(unittest.TestCase):
def _callFUT(self):
from zope.component.globalregistry import getGlobalSiteManager
return getGlobalSiteManager()
def test_gsm_is_IComponentLookup(self):
from zope.component.globalregistry import base
from zope.interface.interfaces import IComponentLookup
gsm = self._callFUT()
self.assertTrue(gsm is base)
self.assertTrue(IComponentLookup.providedBy(gsm))
def test_gsm_is_singleton(self):
gsm = self._callFUT()
self.assertTrue(self._callFUT() is gsm)
def test_gsm_pickling(self):
from zope.component._compat import _pickle
gsm = self._callFUT()
dumped = _pickle.dumps(gsm)
loaded = _pickle.loads(dumped)
self.assertTrue(loaded is gsm)
dumped_utilities = _pickle.dumps(gsm.utilities)
loaded_utilities = _pickle.loads(dumped_utilities)
self.assertTrue(loaded_utilities is gsm.utilities)
dumped_adapters = _pickle.dumps(gsm.adapters)
loaded_adapters = _pickle.loads(dumped_adapters)
self.assertTrue(loaded_adapters is gsm.adapters)
class Test_provideUtility(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def _callFUT(self, *args, **kw):
from zope.component.globalregistry import provideUtility
return provideUtility(*args, **kw)
def test_anonymous_no_provides(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.component.globalregistry import getGlobalSiteManager
class IFoo(Interface):
pass
@implementer(IFoo)
class Foo(object):
pass
foo = Foo()
self._callFUT(foo)
gsm = getGlobalSiteManager()
self.assertIs(gsm.getUtility(IFoo, ''), foo)
# We can clean it up using the fallback and it will be gone
from zope.component.testing import _PlacelessSetupFallback
_PlacelessSetupFallback().cleanUp()
self.assertIsNone(gsm.queryUtility(IFoo, ''))
def test_named_w_provides(self):
from zope.interface import Interface
from zope.component.globalregistry import getGlobalSiteManager
class IFoo(Interface):
pass
class Foo(object):
pass
foo = Foo()
self._callFUT(foo, IFoo, 'named')
gsm = getGlobalSiteManager()
self.assertTrue(gsm.getUtility(IFoo, 'named') is foo)
class Test_provideAdapter(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def _callFUT(self, *args, **kw):
from zope.component.globalregistry import provideAdapter
return provideAdapter(*args, **kw)
def test_anonymous_no_provides_no_adapts(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.component.globalregistry import getGlobalSiteManager
from zope.component._declaration import adapter
class IFoo(Interface):
pass
class IBar(Interface):
pass
@implementer(IFoo)
class Foo(object):
pass
@adapter(IFoo)
@implementer(IBar)
class Bar(object):
def __init__(self, context):
self.context = context
self._callFUT(Bar)
gsm = getGlobalSiteManager()
foo = Foo()
adapted = gsm.getAdapter(foo, IBar)
self.assertTrue(isinstance(adapted, Bar))
self.assertTrue(adapted.context is foo)
def test_named_w_provides_w_adapts(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.component.globalregistry import getGlobalSiteManager
class IFoo(Interface):
pass
class IBar(Interface):
pass
@implementer(IFoo)
class Foo(object):
pass
class Bar(object):
def __init__(self, context):
self.context = context
self._callFUT(Bar, (IFoo,), IBar, 'test')
gsm = getGlobalSiteManager()
foo = Foo()
adapted = gsm.getAdapter(foo, IBar, name='test')
self.assertTrue(isinstance(adapted, Bar))
self.assertTrue(adapted.context is foo)
class Test_provideSubscriptionAdapter(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def _callFUT(self, *args, **kw):
from zope.component.globalregistry import provideSubscriptionAdapter
return provideSubscriptionAdapter(*args, **kw)
def test_no_provides_no_adapts(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.component.globalregistry import getGlobalSiteManager
from zope.component._declaration import adapter
class IFoo(Interface):
pass
class IBar(Interface):
pass
@implementer(IFoo)
class Foo(object):
pass
@adapter(IFoo)
@implementer(IBar)
class Bar(object):
def __init__(self, context):
self.context = context
self._callFUT(Bar)
gsm = getGlobalSiteManager()
foo = Foo()
adapted = gsm.subscribers((foo,), IBar)
self.assertEqual(len(adapted), 1)
self.assertTrue(isinstance(adapted[0], Bar))
self.assertTrue(adapted[0].context is foo)
def test_w_provides_w_adapts(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.component.globalregistry import getGlobalSiteManager
class IFoo(Interface):
pass
class IBar(Interface):
pass
@implementer(IFoo)
class Foo(object):
pass
class Bar(object):
def __init__(self, context):
self.context = context
self._callFUT(Bar, (IFoo,), IBar)
gsm = getGlobalSiteManager()
foo = Foo()
adapted = gsm.subscribers((foo,), IBar)
self.assertEqual(len(adapted), 1)
self.assertTrue(isinstance(adapted[0], Bar))
self.assertTrue(adapted[0].context is foo)
class Test_provideHandler(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def _callFUT(self, *args, **kw):
from zope.component.globalregistry import provideHandler
return provideHandler(*args, **kw)
def test_no_adapts(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.interface import providedBy
from zope.component.globalregistry import getGlobalSiteManager
from zope.component._declaration import adapter
class IFoo(Interface):
pass
@implementer(IFoo)
class Foo(object):
pass
_handler = adapter(IFoo)(fails_if_called(self))
self._callFUT(_handler)
gsm = getGlobalSiteManager()
regs = list(gsm.registeredHandlers())
self.assertEqual(len(regs), 1)
hr = regs[0]
self.assertEqual(list(hr.required), list(providedBy(Foo())))
self.assertEqual(hr.name, '')
self.assertTrue(hr.factory is _handler)
def test_w_adapts(self):
from zope.interface import Interface
from zope.component.globalregistry import getGlobalSiteManager
class IFoo(Interface):
pass
_handler = fails_if_called(self)
self._callFUT(_handler, (IFoo,))
gsm = getGlobalSiteManager()
regs = list(gsm.registeredHandlers())
self.assertEqual(len(regs), 1)
hr = regs[0]
self.assertEqual(list(hr.required), [IFoo])
self.assertEqual(hr.name, '')
self.assertTrue(hr.factory is _handler)
@@ -0,0 +1,352 @@
##############################################################################
#
# Copyright (c) 2012 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.
#
##############################################################################
"""Tests for z.c.hooks
"""
import unittest
class Test_read_property(unittest.TestCase):
def _getTargetClass(self):
from zope.component.hooks import read_property
return read_property
def test_via_instance(self):
class Foo(object):
@self._getTargetClass()
def bar(self):
return 'BAR'
foo = Foo()
self.assertEqual(foo.bar, 'BAR')
foo.bar = 'BAZ'
self.assertEqual(foo.bar, 'BAZ')
del foo.bar
self.assertEqual(foo.bar, 'BAR')
def test_via_class(self):
class Foo(object):
@self._getTargetClass()
def bar(self):
return 'BAR'
bar = Foo.bar
self.assertTrue(isinstance(bar, self._getTargetClass()))
self.assertEqual(bar.func(object()), 'BAR')
class SiteInfoTests(unittest.TestCase):
def _getTargetClass(self):
from zope.component.hooks import SiteInfo
return SiteInfo
def _makeOne(self):
return self._getTargetClass()()
def test_initial(self):
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
si = self._makeOne()
self.assertEqual(si.site, None)
self.assertTrue(si.sm is gsm)
def test_adapter_hook(self):
_hook = object()
class _Registry(object):
adapter_hook = _hook
class _SiteManager(object):
adapters = _Registry()
si = self._makeOne()
si.sm = _SiteManager()
self.assertFalse('adapter_hook' in si.__dict__)
self.assertTrue(si.adapter_hook is _hook)
self.assertTrue('adapter_hook' in si.__dict__)
del si.adapter_hook
self.assertFalse('adapter_hook' in si.__dict__)
class Test_setSite(unittest.TestCase):
def _callFUT(self, site):
from zope.component.hooks import setSite
return setSite(site)
def test_w_None(self):
from zope.component import hooks
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
_SM2 = object()
_SITE = object()
_HOOK = object()
siteinfo = _DummySiteInfo()
siteinfo.sm = _SM2
siteinfo.site = _SITE
siteinfo.adapterhook = _HOOK
with _Monkey(hooks, siteinfo=siteinfo):
self._callFUT(None)
self.assertTrue(siteinfo.sm is gsm)
self.assertTrue(siteinfo.site is None)
self.assertFalse('adapter_hook' in siteinfo.__dict__)
def test_w_site(self):
from zope.component import hooks
_SM2 = object()
class _Site(object):
def getSiteManager(self):
return _SM2
siteinfo = _DummySiteInfo()
_site = _Site()
with _Monkey(hooks, siteinfo=siteinfo):
self._callFUT(_site)
self.assertTrue(siteinfo.sm is _SM2)
self.assertTrue(siteinfo.site is _site)
self.assertFalse('adapter_hook' in siteinfo.__dict__)
class Test_getSite(unittest.TestCase):
def _callFUT(self):
from zope.component.hooks import getSite
return getSite()
def test_w_None(self):
from zope.component import hooks
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
siteinfo = _DummySiteInfo()
with _Monkey(hooks, siteinfo=siteinfo):
self.assertTrue(self._callFUT() is None)
def test_w_site(self):
from zope.component import hooks
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
_SM2 = object()
_SITE = object()
siteinfo = _DummySiteInfo()
siteinfo.sm = _SM2
siteinfo.site = _SITE
with _Monkey(hooks, siteinfo=siteinfo):
self.assertTrue(self._callFUT() is _SITE)
class Test_site(unittest.TestCase):
def _callFUT(self, new_site):
from zope.component.hooks import site
return site(new_site)
def test_it(self):
from zope.component import hooks
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
_SM2 = object()
class _Site(object):
def getSiteManager(self):
return _SM2
_site = _Site()
siteinfo = _DummySiteInfo()
self.assertTrue(siteinfo.site is None)
self.assertTrue(siteinfo.sm is _SM)
with _Monkey(hooks, siteinfo=siteinfo):
with self._callFUT(_site):
self.assertTrue(siteinfo.site is _site)
self.assertTrue(siteinfo.sm is _SM2)
self.assertTrue(siteinfo.site is None)
self.assertTrue(siteinfo.sm is gsm)
class Test_getSiteManager(unittest.TestCase):
def _callFUT(self, context=None):
from zope.component.hooks import getSiteManager
return getSiteManager(context)
def test_default(self):
from zope.component import hooks
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
_SM2 = object()
siteinfo = _DummySiteInfo()
siteinfo.sm = _SM2
with _Monkey(hooks, siteinfo=siteinfo):
self.assertTrue(self._callFUT() is _SM2)
def test_w_explicit_context_no_IComponentLookup(self):
from zope.component import hooks
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
_SM2 = object()
siteinfo = _DummySiteInfo()
siteinfo.sm = _SM2
with _Monkey(hooks, siteinfo=siteinfo):
self.assertTrue(self._callFUT(object()) is gsm)
def test_w_explicit_context_w_IComponentLookup(self):
from zope.interface import Interface
from zope.component import hooks
from zope.component.globalregistry import getGlobalSiteManager
from zope.interface.interfaces import IComponentLookup
class _Lookup(object):
def __init__(self, context):
self.context = context
gsm = getGlobalSiteManager()
gsm.registerAdapter(_Lookup, (Interface,), IComponentLookup, '')
_SM2 = object()
siteinfo = _DummySiteInfo()
siteinfo.sm = _SM2
context = object()
with _Monkey(hooks, siteinfo=siteinfo):
sm = self._callFUT(context)
self.assertTrue(isinstance(sm, _Lookup))
self.assertTrue(sm.context is context)
class Test_adapter_hook(unittest.TestCase):
def _callFUT(self, interface, object, name='', default=None):
from zope.component.hooks import adapter_hook
return adapter_hook(interface, object, name, default)
def test_success(self):
from zope.interface import Interface
from zope.component import hooks
from zope.component.globalregistry import getGlobalSiteManager
class IFoo(Interface):
pass
gsm = getGlobalSiteManager()
_ADAPTER = object()
_DEFAULT = object()
_CONTEXT = object()
_called = []
def _adapter_hook(interface, object, name, default):
_called.append((interface, object, name, default))
return _ADAPTER
siteinfo = _DummySiteInfo()
siteinfo.adapter_hook = _adapter_hook
with _Monkey(hooks, siteinfo=siteinfo):
adapter = self._callFUT(IFoo, _CONTEXT, 'bar', _DEFAULT)
self.assertTrue(adapter is _ADAPTER)
self.assertEqual(_called, [(IFoo, _CONTEXT, 'bar', _DEFAULT)])
def test_hook_raises(self):
from zope.interface import Interface
from zope.component import hooks
from zope.component.globalregistry import getGlobalSiteManager
from zope.interface.interfaces import ComponentLookupError
class IFoo(Interface):
pass
gsm = getGlobalSiteManager()
_DEFAULT = object()
_CONTEXT = object()
_called = []
def _adapter_hook(interface, object, name, default):
_called.append((interface, object, name, default))
raise ComponentLookupError('testing')
siteinfo = _DummySiteInfo()
siteinfo.adapter_hook = _adapter_hook
with _Monkey(hooks, siteinfo=siteinfo):
adapter = self._callFUT(IFoo, _CONTEXT, 'bar', _DEFAULT)
self.assertTrue(adapter is _DEFAULT)
self.assertEqual(_called, [(IFoo, _CONTEXT, 'bar', _DEFAULT)])
class Test_setHooks(unittest.TestCase):
def _callFUT(self):
from zope.component.hooks import setHooks
return setHooks()
def test_it(self):
import zope.component._api
from zope.component import hooks
class _Hook(object):
def __init__(self):
self._hooked = None
def sethook(self, value):
self._hooked = value
adapter_hook = _Hook()
getSiteManager = _Hook()
with _Monkey(zope.component._api,
adapter_hook=adapter_hook,
getSiteManager=getSiteManager):
self._callFUT()
self.assertEqual(adapter_hook._hooked, hooks.adapter_hook)
self.assertEqual(getSiteManager._hooked, hooks.getSiteManager)
class Test_resetHooks(unittest.TestCase):
def _callFUT(self):
from zope.component.hooks import resetHooks
return resetHooks()
def test_it(self):
import zope.component._api
from zope.component import hooks
class _Hook(object):
def __init__(self):
self._reset = False
def reset(self):
self._reset = True
adapter_hook = _Hook()
getSiteManager = _Hook()
with _Monkey(zope.component._api,
adapter_hook=adapter_hook,
getSiteManager=getSiteManager):
# Access the adapter_hook of the site info to be
# sure it caches
getattr(hooks.siteinfo, 'adapter_hook')
self.assertTrue('adapter_hook' in hooks.siteinfo.__dict__)
self._callFUT()
self.assertTrue(adapter_hook._reset)
self.assertTrue(getSiteManager._reset)
# adapter_hook cache also reset
self.assertFalse('adapter_hook' in hooks.siteinfo.__dict__)
_SM = object()
class _DummySiteInfo(object):
sm = _SM
site = None
class _Monkey(object):
# context-manager for replacing module names in the scope of a test.
def __init__(self, module, **kw):
self.module = module
self.to_restore = dict([(key, getattr(module, key)) for key in kw])
for key, value in kw.items():
setattr(module, key, value)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
for key, value in self.to_restore.items():
setattr(self.module, key, value)
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(Test_read_property),
unittest.makeSuite(SiteInfoTests),
unittest.makeSuite(Test_setSite),
unittest.makeSuite(Test_getSite),
unittest.makeSuite(Test_site),
unittest.makeSuite(Test_getSiteManager),
unittest.makeSuite(Test_adapter_hook),
unittest.makeSuite(Test_setHooks),
unittest.makeSuite(Test_resetHooks),
))
@@ -0,0 +1,396 @@
##############################################################################
#
# Copyright (c) 2012 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.
#
##############################################################################
"""Tests for z.c.interface
"""
import unittest
class Test_provideInterface(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def _callFUT(self, *args, **kw):
from zope.component.interface import provideInterface
return provideInterface(*args, **kw)
def test_w_interface_not_IInterface(self):
self.assertRaises(TypeError, self._callFUT, 'xxx', object())
def test_w_iface_type_not_IInterface(self):
from zope.interface import Interface
from zope.interface.interface import InterfaceClass
class IFoo(Interface):
pass
IBar = InterfaceClass('IBar')
self.assertRaises(TypeError, self._callFUT, 'xxx', IFoo, IBar)
def test_w_class(self):
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IBar(IInterface):
pass
class Foo(object):
pass
self._callFUT('', Foo, IBar)
self.assertFalse(IBar.providedBy(Foo))
self.assertEqual(len(list(gsm.getUtilitiesFor(IBar))), 0)
def test_wo_name_w_iface_type(self):
from zope.interface import Interface
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IFoo(Interface):
pass
class IBar(IInterface):
pass
self._callFUT('', IFoo, IBar)
self.assertTrue(IBar.providedBy(IFoo))
nm = 'zope.component.tests.test_interface.IFoo'
self.assertTrue(gsm.getUtility(IBar, nm) is IFoo)
def test_w_name_wo_ifact_type(self):
from zope.interface import Interface
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IFoo(Interface):
pass
self._callFUT('foo', IFoo)
self.assertTrue(IInterface.providedBy(IFoo))
registered = gsm.getUtility(IInterface, name='foo')
self.assertTrue(registered is IFoo)
class Test_getInterface(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def _callFUT(self, *args, **kw):
from zope.component.interface import getInterface
return getInterface(*args, **kw)
def test_miss(self):
from zope.interface.interfaces import ComponentLookupError
self.assertRaises(ComponentLookupError,
self._callFUT, object(), 'nonesuch')
def test_hit(self):
from zope.interface import Interface
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IFoo(Interface):
pass
gsm.registerUtility(IFoo, IInterface, 'foo')
self.assertTrue(self._callFUT(object(), 'foo') is IFoo)
class Test_queryInterface(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def _callFUT(self, *args, **kw):
from zope.component.interface import queryInterface
return queryInterface(*args, **kw)
def test_miss(self):
_DEFAULT = object()
self.assertTrue(
self._callFUT('nonesuch', default=_DEFAULT) is _DEFAULT)
def test_hit(self):
from zope.interface import Interface
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IFoo(Interface):
pass
gsm.registerUtility(IFoo, IInterface, 'foo')
self.assertTrue(self._callFUT('foo') is IFoo)
class Test_searchInterface(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def _callFUT(self, *args, **kw):
from zope.component.interface import searchInterface
return searchInterface(*args, **kw)
def test_empty(self):
self.assertEqual(self._callFUT(object()), [])
def test_no_search_string_no_base(self):
from zope.interface import Interface
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IFoo(Interface):
pass
gsm.registerUtility(IFoo, IInterface, 'foo')
self.assertEqual(self._callFUT(object()), [IFoo])
def test_w_search_string_no_base(self):
from zope.interface import Interface
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IFoo(Interface):
pass
class IBar(Interface):
pass
gsm.registerUtility(IFoo, IInterface, 'foo')
gsm.registerUtility(IBar, IInterface, 'bar')
self.assertEqual(self._callFUT(object(), 'IFoo'), [IFoo])
def test_no_search_string_w_base(self):
from zope.interface import Interface
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IBase(Interface):
pass
class IFoo(IBase):
pass
class IBar(Interface):
pass
gsm.registerUtility(IFoo, IInterface, 'foo')
gsm.registerUtility(IBar, IInterface, 'bar')
self.assertEqual(self._callFUT(object(), base=IBase), [IFoo])
class Test_searchInterfaceIds(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def _callFUT(self, *args, **kw):
from zope.component.interface import searchInterfaceIds
return searchInterfaceIds(*args, **kw)
def test_empty(self):
self.assertEqual(self._callFUT(object()), [])
def test_no_search_string_no_base(self):
from zope.interface import Interface
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IFoo(Interface):
pass
gsm.registerUtility(IFoo, IInterface, 'foo')
self.assertEqual(self._callFUT(object()), ['foo'])
def test_w_search_string_no_base(self):
from zope.interface import Interface
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IFoo(Interface):
pass
class IBar(Interface):
pass
gsm.registerUtility(IFoo, IInterface, 'foo')
gsm.registerUtility(IBar, IInterface, 'bar')
self.assertEqual(self._callFUT(object(), 'IFoo'), ['foo'])
def test_no_search_string_w_base(self):
from zope.interface import Interface
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IBase(Interface):
pass
class IFoo(IBase):
pass
class IBar(Interface):
pass
gsm.registerUtility(IFoo, IInterface, 'foo')
gsm.registerUtility(IBar, IInterface, 'bar')
self.assertEqual(self._callFUT(object(), base=IBase), ['foo'])
class Test_searchInterfaceUtilities(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def _callFUT(self, *args, **kw):
from zope.component.interface import searchInterfaceUtilities
return searchInterfaceUtilities(*args, **kw)
def test_empty(self):
self.assertEqual(self._callFUT(object()), [])
def test_no_search_string_no_base(self):
from zope.interface import Interface
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IFoo(Interface):
pass
gsm.registerUtility(IFoo, IInterface, 'foo')
self.assertEqual(self._callFUT(object()), [('foo', IFoo)])
def test_w_search_string_no_base(self):
from zope.interface import Interface
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IFoo(Interface):
pass
class IBar(Interface):
pass
gsm.registerUtility(IFoo, IInterface, 'foo')
gsm.registerUtility(IBar, IInterface, 'bar')
self.assertEqual(self._callFUT(object(), 'IFoo'), [('foo', IFoo)])
def test_no_search_string_w_base(self):
from zope.interface import Interface
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IBase(Interface):
pass
class IFoo(IBase):
pass
class IBar(Interface):
pass
gsm.registerUtility(IFoo, IInterface, 'foo')
gsm.registerUtility(IBar, IInterface, 'bar')
self.assertEqual(self._callFUT(object(), base=IBase), [('foo', IFoo)])
def test_no_search_string_w_base_is_same(self):
from zope.interface import Interface
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IFoo(Interface):
pass
class IBar(Interface):
pass
gsm.registerUtility(IFoo, IInterface, 'foo')
gsm.registerUtility(IBar, IInterface, 'bar')
self.assertEqual(self._callFUT(object(), base=IFoo), [('foo', IFoo)])
class Test_getInterfaceAllDocs(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.component.interface import getInterfaceAllDocs
return getInterfaceAllDocs(*args, **kw)
def test_w_class(self):
class Foo(object):
"""DOCSTRING"""
bar = None
def baz(self):
"""BAZ"""
self.assertEqual(self._callFUT(Foo),
'zope.component.tests.test_interface.foo\n' +
'docstring')
def test_w_interface_no_members(self):
from zope.interface import Interface
class IFoo(Interface):
"""DOCSTRING"""
self.assertEqual(self._callFUT(IFoo),
'zope.component.tests.test_interface.ifoo\n' +
'docstring')
def test_w_interface_w_members(self):
from zope.interface import Attribute
from zope.interface import Interface
class IFoo(Interface):
"""DOCSTRING"""
bar = Attribute('bar', 'Do bar')
def baz(self):
"""BAZ"""
self.assertEqual(self._callFUT(IFoo),
'zope.component.tests.test_interface.ifoo\n' +
'docstring\n' +
'do bar\n' +
'baz')
class Test_nameToInterface(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def _callFUT(self, *args, **kw):
from zope.component.interface import nameToInterface
return nameToInterface(*args, **kw)
def test_w_None(self):
self.assertTrue(self._callFUT(object(), 'None') is None)
def test_miss(self):
from zope.interface.interfaces import ComponentLookupError
self.assertRaises(ComponentLookupError,
self._callFUT, object(), 'nonesuch')
def test_hit(self):
from zope.interface import Interface
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IFoo(Interface):
pass
gsm.registerUtility(IFoo, IInterface, 'foo')
found = self._callFUT(object(), 'foo')
self.assertTrue(found is IFoo)
class Test_interfaceToName(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def _callFUT(self, *args, **kw):
from zope.component.interface import interfaceToName
return interfaceToName(*args, **kw)
def test_w_None(self):
self.assertEqual(self._callFUT(object(), None), 'None')
def test_w_unregistered(self):
from zope.interface import Interface
class IFoo(Interface):
pass
self.assertEqual(self._callFUT(object(), IFoo),
'zope.component.tests.test_interface.IFoo')
def test_w_registered(self):
from zope.interface import Interface
from zope.interface.interfaces import IInterface
from zope.component.globalregistry import getGlobalSiteManager
gsm = getGlobalSiteManager()
class IFoo(Interface):
pass
gsm.registerUtility(IFoo, IInterface, 'foo')
self.assertEqual(self._callFUT(object(), IFoo),
'zope.component.tests.test_interface.IFoo')
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(Test_provideInterface),
unittest.makeSuite(Test_getInterface),
unittest.makeSuite(Test_queryInterface),
unittest.makeSuite(Test_searchInterface),
unittest.makeSuite(Test_searchInterfaceIds),
unittest.makeSuite(Test_searchInterfaceUtilities),
unittest.makeSuite(Test_getInterfaceAllDocs),
unittest.makeSuite(Test_nameToInterface),
unittest.makeSuite(Test_interfaceToName),
))
@@ -0,0 +1,53 @@
##############################################################################
#
# Copyright (c) 2017 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.
#
##############################################################################
"""
Tests for zope.component.interfaces
"""
import unittest
class TestBackwardsCompat(unittest.TestCase):
def test_interface_warnings(self):
from zope.component import interfaces
import warnings
for name in (
'ComponentLookupError',
'Invalid',
'IObjectEvent',
'ObjectEvent',
'IComponentLookup',
'IRegistration',
'IUtilityRegistration',
'_IBaseAdapterRegistration',
'IAdapterRegistration',
'ISubscriptionAdapterRegistration',
'IHandlerRegistration',
'IRegistrationEvent',
'RegistrationEvent',
'IRegistered',
'Registered',
'IUnregistered',
'Unregistered',
'IComponentRegistry',
'IComponents',
):
with warnings.catch_warnings(record=True) as log:
warnings.simplefilter("always")
getattr(interfaces, name)
self.assertEqual(1, len(log), name)
message = str(log[0].message)
self.assertIn(name, message)
self.assertIn("Import from zope.interface.interfaces", message)
@@ -0,0 +1,163 @@
##############################################################################
#
# Copyright (c) 2012 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.
#
##############################################################################
"""Tests for z.c.hooks
"""
import unittest
def skipIfNoPersistent(testfunc):
try:
import persistent
except ImportError: # pragma: no cover
return unittest.skip("persistent not installed")(testfunc)
return testfunc
@skipIfNoPersistent
class PersistentAdapterRegistryTests(unittest.TestCase):
def _getTargetClass(self):
from zope.component.persistentregistry import PersistentAdapterRegistry
return PersistentAdapterRegistry
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def _makeCache(self, jar):
# Borrowed from persistent.tests.test_pyPersistence.
class _Cache(object):
def __init__(self, jar):
self._jar = jar
self._mru = []
# mru(oid) is only called in pure-Python runs
self.mru = self._mru.append
def new_ghost(self, oid, obj):
obj._p_jar = self._jar
obj._p_oid = oid
def update_object_size_estimation(self, oid, size):
"This is only called in pure-Python runs"
return _Cache(jar)
def _makeJar(self):
# Borrowed from persistent.tests.test_pyPersistence.
from zope.interface import implementer
from persistent.interfaces import IPersistentDataManager
@implementer(IPersistentDataManager)
class _Jar(object):
def __init__(self):
self._loaded = []
self._registered = []
def setstate(self, obj):
self._loaded.append(obj._p_oid)
def register(self, obj):
self._registered.append(obj._p_oid)
jar = _Jar()
jar._cache = self._makeCache(jar)
return jar
def _makeOneWithJar(self, dirty=False, **kw):
# Borrowed from persistent.tests.test_pyPersistence.
OID = _makeOctets('\x01' * 8)
inst = self._makeOne(**kw)
jar = self._makeJar()
jar._cache.new_ghost(OID, inst) # assigns _p_jar, _p_oid
return inst, jar, OID
def test_changed_original_is_not_us(self):
registry, jar, OID = self._makeOneWithJar()
self.assertEqual(registry._generation, 1)
registry.changed(object())
# 'originally_changed' is not us, but we are still dirty because
# '_generation' gets bumped.
self.assertEqual(registry._p_changed, True)
# base class gets called
self.assertEqual(registry._generation, 2)
def test_changed_original_is_us(self):
registry, jar, OID = self._makeOneWithJar()
self.assertEqual(registry._generation, 1)
registry.changed(registry)
# 'originally_changed' is not us, so not dirty
self.assertEqual(registry._p_changed, True)
# base class gets called
self.assertEqual(registry._generation, 2)
def test___getstate___simple(self):
from zope.component import globalSiteManager
bases = (globalSiteManager.adapters, globalSiteManager.utilities)
registry, jar, OID = self._makeOneWithJar(bases=bases)
state = registry.__getstate__()
self.assertEqual(state['__bases__'], bases)
self.assertEqual(state['_generation'], 1)
self.assertEqual(state['_provided'], {})
self.assertEqual(state['_adapters'], [])
self.assertEqual(state['_subscribers'], [])
self.assertFalse('ro' in state)
def test___getstate___skips_delegated_names(self):
registry, jar, OID = self._makeOneWithJar()
registry.names = lambda *args: ['a', 'b', 'c']
self.assertFalse('names' in registry.__getstate__())
def test___setstate___rebuilds__v_lookup(self):
registry, jar, OID = self._makeOneWithJar()
state = registry.__getstate__()
self.assertTrue('_v_lookup' in registry.__dict__)
registry._p_changed = None # clears volatile '_v_lookup'
self.assertFalse('_v_lookup' in registry.__dict__)
registry.__setstate__(state)
self.assertTrue('_v_lookup' in registry.__dict__)
def test___setstate___rebuilds__ro(self):
from zope.component import globalSiteManager
bases = (globalSiteManager.adapters, globalSiteManager.utilities)
registry, jar, OID = self._makeOneWithJar(bases=bases)
state = registry.__getstate__()
registry.__setstate__(state)
self.assertEqual(registry.__bases__, bases)
self.assertEqual(registry.ro, [registry] + list(bases))
@skipIfNoPersistent
class PersistentComponentsTests(unittest.TestCase):
def _getTargetClass(self):
from zope.component.persistentregistry import PersistentComponents
return PersistentComponents
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test_ctor_initializes_registries_and_registrations(self):
from persistent.mapping import PersistentMapping
from persistent.list import PersistentList
from zope.component.persistentregistry import PersistentAdapterRegistry
registry = self._makeOne()
self.assertTrue(isinstance(registry.adapters,
PersistentAdapterRegistry))
self.assertTrue(isinstance(registry.utilities,
PersistentAdapterRegistry))
self.assertTrue(isinstance(registry._adapter_registrations,
PersistentMapping))
self.assertTrue(isinstance(registry._utility_registrations,
PersistentMapping))
self.assertTrue(isinstance(registry._subscription_registrations,
PersistentList))
self.assertTrue(isinstance(registry._handler_registrations,
PersistentList))
def _makeOctets(s):
return bytes(s) if bytes is str else bytes(s, 'ascii')
@@ -0,0 +1,146 @@
##############################################################################
#
# Copyright (c) 2012 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.
#
##############################################################################
"""Tests for z.c.registry
"""
import unittest
from zope.component.tests import fails_if_called
class Test_dispatchUtilityRegistrationEvent(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def _callFUT(self, *args, **kw):
from zope.component.registry import dispatchUtilityRegistrationEvent
return dispatchUtilityRegistrationEvent(*args, **kw)
def test_it(self):
from zope.component import registry
class _Registration(object):
component = object()
_EVENT = object()
_handled = []
def _handle(*args):
_handled.append(args)
with _Monkey(registry, handle=_handle):
self._callFUT(_Registration(), _EVENT)
self.assertEqual(_handled, [(_Registration.component, _EVENT)])
class Test_dispatchAdapterRegistrationEvent(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def _callFUT(self, *args, **kw):
from zope.component.registry import dispatchAdapterRegistrationEvent
return dispatchAdapterRegistrationEvent(*args, **kw)
def test_it(self):
from zope.component import registry
class _Registration(object):
factory = fails_if_called(self)
_registration = _Registration()
_EVENT = object()
_handled = []
def _handle(*args):
_handled.append(args)
with _Monkey(registry, handle=_handle):
self._callFUT(_registration, _EVENT)
self.assertEqual(_handled, [(_registration.factory, _EVENT)])
class Test_dispatchSubscriptionAdapterRegistrationEvent(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def _callFUT(self, *args, **kw):
from zope.component.registry \
import dispatchSubscriptionAdapterRegistrationEvent
return dispatchSubscriptionAdapterRegistrationEvent(*args, **kw)
def test_it(self):
from zope.component import registry
class _Registration(object):
factory = fails_if_called(self)
_registration = _Registration()
_EVENT = object()
_handled = []
def _handle(*args):
_handled.append(args)
with _Monkey(registry, handle=_handle):
self._callFUT(_registration, _EVENT)
self.assertEqual(_handled, [(_registration.factory, _EVENT)])
class Test_dispatchHandlerRegistrationEvent(unittest.TestCase):
from zope.component.testing import setUp, tearDown
def _callFUT(self, *args, **kw):
from zope.component.registry import dispatchHandlerRegistrationEvent
return dispatchHandlerRegistrationEvent(*args, **kw)
def test_it(self):
from zope.component import registry
class _Registration(object):
handler = fails_if_called(self)
_registration = _Registration()
_EVENT = object()
_handled = []
def _handle(*args):
_handled.append(args)
with _Monkey(registry, handle=_handle):
self._callFUT(_registration, _EVENT)
self.assertEqual(_handled, [(_registration.handler, _EVENT)])
class TestBackwardsCompat(unittest.TestCase):
def test_interface_warnings(self):
from zope.component import registry
import warnings
for name in (
'Components',
'_getUtilityProvided',
'_getAdapterProvided',
'_getAdapterRequired',
'UtilityRegistration',
'AdapterRegistration',
'SubscriptionRegistration',
'HandlerRegistration',
):
with warnings.catch_warnings(record=True) as log:
warnings.simplefilter("always")
getattr(registry, name)
self.assertEqual(1, len(log), name)
message = str(log[0].message)
self.assertIn(name, message)
self.assertIn("Import from zope.interface.registry", message)
class _Monkey(object):
# context-manager for replacing module names in the scope of a test.
def __init__(self, module, **kw):
self.module = module
self.to_restore = dict([(key, getattr(module, key)) for key in kw])
for key, value in kw.items():
setattr(module, key, value)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
for key, value in self.to_restore.items():
setattr(self.module, key, value)
@@ -0,0 +1,240 @@
##############################################################################
#
# Copyright (c) 2012 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.
#
##############################################################################
"""
Tests for zope.component.security
"""
import unittest
from zope.component.tests import skipIfNoSecurity
from zope.component.tests import fails_if_called
@skipIfNoSecurity
class PermissionProxyTests(unittest.TestCase):
def _getTargetClass(self):
from zope.component.security import PermissionProxy
return PermissionProxy
def _makeOne(self, wrapped):
return self._getTargetClass()(wrapped)
def test_proxy_delegates___provided_by__(self):
from zope.interface import Interface
from zope.interface import implementer
from zope.interface import providedBy
class IFoo(Interface):
pass
@implementer(IFoo)
class Foo(object):
pass
foo = Foo()
proxy = self._makeOne(foo)
self.assertEqual(providedBy(proxy), providedBy(foo))
@skipIfNoSecurity
class Test__checker(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.component.security import _checker
return _checker(*args, **kw)
def test_no_allowed_attributes_no_allowed_interfaces(self):
from zope.security.checker import CheckerPublic
checker = self._callFUT(object(), 'zope.Public', (), ())
self.assertEqual(checker.get_permissions, {'__call__': CheckerPublic})
self.assertFalse(checker.set_permissions)
def test_w_allowed_interfaces(self):
from zope.interface import Interface
class IFoo(Interface):
def bar(self):
"bar"
def baz(self):
"baz"
class ISpam(Interface):
def qux(self):
"qux"
checker = self._callFUT(object(), 'testing', (IFoo, ISpam), ())
self.assertEqual(checker.get_permissions,
{'bar': 'testing', 'baz': 'testing', 'qux': 'testing'})
self.assertFalse(checker.set_permissions)
def test_w_allowed_attributes(self):
checker = self._callFUT(object(), 'testing', (), ('foo', 'bar'))
self.assertEqual(checker.get_permissions,
{'foo': 'testing', 'bar': 'testing'})
self.assertFalse(checker.set_permissions)
@skipIfNoSecurity
class Test_proxify(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.component.security import proxify
return proxify(*args, **kw)
def _makeContext(self):
class _Context(object):
bar = fails_if_called(self)
return _Context()
def test_no_checker_no_provides(self):
ctx = self._makeContext()
self.assertRaises(ValueError, self._callFUT, ctx, permission='testing')
def test_no_checker_no_permission(self):
from zope.interface import Interface
class IFoo(Interface):
def bar(self):
"bar"
ctx = self._makeContext()
self.assertRaises(ValueError, self._callFUT, ctx, provides=IFoo)
def test_no_checker_w_provides_and_permission_public(self):
from zope.interface import Interface
from zope.security.checker import CheckerPublic
from zope.proxy import getProxiedObject
class IFoo(Interface):
def bar(self):
"bar"
ctx = self._makeContext()
proxy = self._callFUT(ctx, provides=IFoo, permission='zope.Public')
self.assertTrue(getProxiedObject(proxy) is ctx)
checker = proxy.__Security_checker__
self.assertEqual(checker.get_permissions, {'bar': CheckerPublic})
self.assertFalse(checker.set_permissions)
def test_no_checker_w_provides_and_permission_protected(self):
from zope.interface import Interface
from zope.proxy import getProxiedObject
class IFoo(Interface):
def bar(self):
"bar"
ctx = self._makeContext()
proxy = self._callFUT(ctx, provides=IFoo, permission='testing')
self.assertTrue(getProxiedObject(proxy) is ctx)
checker = proxy.__Security_checker__
self.assertEqual(checker.get_permissions, {'bar': 'testing'})
self.assertFalse(checker.set_permissions)
def test_w_checker(self):
from zope.proxy import getProxiedObject
_CHECKER = object()
ctx = self._makeContext()
proxy = self._callFUT(ctx, _CHECKER)
self.assertTrue(getProxiedObject(proxy) is ctx)
self.assertTrue(proxy.__Security_checker__ is _CHECKER)
@skipIfNoSecurity
class Test_protectedFactory(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.component.security import protectedFactory
return protectedFactory(*args, **kw)
def test_public_not_already_proxied(self):
from zope.interface import Interface
from zope.security.checker import CheckerPublic
class IFoo(Interface):
def bar(self):
"bar"
class _Factory(object):
bar = fails_if_called(self)
protected = self._callFUT(_Factory, IFoo, 'zope.Public')
self.assertTrue(protected.factory is _Factory)
foo = protected()
self.assertEqual(foo.__Security_checker__.get_permissions,
{'bar': CheckerPublic})
def test_nonpublic_already_proxied(self):
from zope.interface import Interface
from zope.security.proxy import getTestProxyItems
class IFoo(Interface):
def bar(self):
"bar"
class _Factory(object):
__slots__ = ('one',)
bar = fails_if_called(self)
protected = self._callFUT(_Factory, IFoo, 'testing')
self.assertTrue(protected.factory is _Factory)
foo = protected()
self.assertEqual(getTestProxyItems(foo), [('bar', 'testing')])
@skipIfNoSecurity
class Test_securityAdapterFactory(unittest.TestCase):
def _callFUT(self, *args, **kw):
from zope.component.security import securityAdapterFactory
return securityAdapterFactory(*args, **kw)
def test_no_permission_untrusted_no_location(self):
class _Factory(object):
pass
self.assertTrue(self._callFUT(_Factory, None, False, False)
is _Factory)
def test_public_untrusted_no_location(self):
class _Factory(object):
pass
self.assertTrue(self._callFUT(_Factory, 'zope.Public', False, False)
is _Factory)
def test_CheckerPublic_untrusted_no_location(self):
from zope.security.checker import CheckerPublic
class _Factory(object):
pass
self.assertTrue(self._callFUT(_Factory, CheckerPublic, False, False)
is _Factory)
def test_protected_untrusted_no_location(self):
from zope.security.adapter import LocatingUntrustedAdapterFactory
class _Factory(object):
pass
proxy = self._callFUT(_Factory, 'testing', False, False)
self.assertTrue(isinstance(proxy, LocatingUntrustedAdapterFactory))
def test_no_permission_trusted_no_location(self):
from zope.security.adapter import LocatingTrustedAdapterFactory
class _Factory(object):
pass
proxy = self._callFUT(_Factory, None, False, True)
self.assertTrue(isinstance(proxy, LocatingTrustedAdapterFactory))
def test_public_trusted_no_location(self):
from zope.security.adapter import LocatingTrustedAdapterFactory
class _Factory(object):
pass
proxy = self._callFUT(_Factory, 'zope.Public', False, True)
self.assertTrue(isinstance(proxy, LocatingTrustedAdapterFactory))
def test_CheckerPublic_trusted_no_location(self):
from zope.security.adapter import LocatingTrustedAdapterFactory
from zope.security.checker import CheckerPublic
class _Factory(object):
pass
proxy = self._callFUT(_Factory, CheckerPublic, False, True)
self.assertTrue(isinstance(proxy, LocatingTrustedAdapterFactory))
def test_protected_trusted_no_location(self):
from zope.security.adapter import LocatingTrustedAdapterFactory
class _Factory(object):
pass
proxy = self._callFUT(_Factory, 'testing', False, True)
self.assertTrue(isinstance(proxy, LocatingTrustedAdapterFactory))
def test_protected_trusted_w_location(self):
from zope.security.adapter import LocatingTrustedAdapterFactory
class _Factory(object):
pass
proxy = self._callFUT(_Factory, 'testing', True, True)
self.assertTrue(isinstance(proxy, LocatingTrustedAdapterFactory))
@@ -0,0 +1,55 @@
##############################################################################
#
# Copyright (c) 2001, 2002, 2009 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.
#
##############################################################################
"""Component Architecture Tests
"""
import unittest
from zope.component.tests import skipIfNoSecurity
@skipIfNoSecurity
class StandaloneTests(unittest.TestCase):
def testStandalone(self):
# See: https://bugs.launchpad.net/zope3/+bug/98401
import subprocess
import sys
import os
import pickle
executable = os.path.abspath(sys.executable)
where = os.path.dirname(os.path.dirname(__file__))
program = os.path.join(where, 'standalonetests.py')
process = subprocess.Popen([executable, program],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
stdin=subprocess.PIPE)
try:
pickle.dump(sys.path, process.stdin)
process.stdin.close()
try:
rc = process.wait()
except OSError as e: # pragma: no cover
# MacIntel raises apparently unimportant EINTR?
if e.errno != 4:
raise # TODO verify sanity of a pass on EINTR :-/
if rc != 0: # pragma: no cover
output = process.stdout.read()
if isinstance(output, bytes):
output = output.decode()
sys.stderr.write('#' * 80 + '\n')
sys.stdout.write(output)
sys.stderr.write('#' * 80 + '\n')
self.fail('Output code: %d' % rc)
finally:
process.stdout.close()
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,649 @@
##############################################################################
#
# 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.
#
##############################################################################
"""Component Architecture configuration handlers
"""
from zope.configuration.exceptions import ConfigurationError
from zope.configuration.fields import Bool
from zope.configuration.fields import GlobalInterface
from zope.configuration.fields import GlobalObject
from zope.configuration.fields import PythonIdentifier
from zope.configuration.fields import Tokens
from zope.i18nmessageid import MessageFactory
from zope.interface import Interface
from zope.interface import implementedBy
from zope.interface import providedBy
from zope.schema import TextLine
from zope.component._api import getSiteManager
from zope.component._declaration import adaptedBy, getName
from zope.component.interface import provideInterface
try:
from zope.security.zcml import Permission
except ImportError: #pragma NO COVER
def _no_security(*args, **kw):
raise ConfigurationError("security proxied components are not "
"supported because zope.security is not available")
_checker = proxify = protectedFactory = security =_no_security
Permission = TextLine
else:
from zope.component.security import _checker
from zope.component.security import proxify
from zope.component.security import protectedFactory
from zope.component.security import securityAdapterFactory
_ = MessageFactory('zope')
class ComponentConfigurationError(ValueError, ConfigurationError):
pass
def handler(methodName, *args, **kwargs):
method = getattr(getSiteManager(), methodName)
method(*args, **kwargs)
class IBasicComponentInformation(Interface):
component = GlobalObject(
title=_("Component to use"),
description=_("Python name of the implementation object. This"
" must identify an object in a module using the"
" full dotted name. If specified, the"
" ``factory`` field must be left blank."),
required=False,
)
permission = Permission(
title=_("Permission"),
description=_("Permission required to use this component."),
required=False,
)
factory = GlobalObject(
title=_("Factory"),
description=_("Python name of a factory which can create the"
" implementation object. This must identify an"
" object in a module using the full dotted name."
" If specified, the ``component`` field must"
" be left blank."),
required=False,
)
class IAdapterDirective(Interface):
"""
Register an adapter
"""
factory = Tokens(
title=_("Adapter factory/factories"),
description=_("A list of factories (usually just one) that create"
" the adapter instance."),
required=True,
value_type=GlobalObject()
)
provides = GlobalInterface(
title=_("Interface the component provides"),
description=_("This attribute specifies the interface the adapter"
" instance must provide."),
required=False,
)
for_ = Tokens(
title=_("Specifications to be adapted"),
description=_("This should be a list of interfaces or classes"),
required=False,
value_type=GlobalObject(
missing_value=object(),
),
)
permission = Permission(
title=_("Permission"),
description=_("This adapter is only available, if the principal"
" has this permission."),
required=False,
)
name = TextLine(
title=_("Name"),
description=_("Adapters can have names.\n\n"
"This attribute allows you to specify the name for"
" this adapter."),
required=False,
)
trusted = Bool(
title=_("Trusted"),
description=_("""Make the adapter a trusted adapter
Trusted adapters have unfettered access to the objects they
adapt. If asked to adapt security-proxied objects, then,
rather than getting an unproxied adapter of security-proxied
objects, you get a security-proxied adapter of unproxied
objects.
"""),
required=False,
default=False,
)
locate = Bool(
title=_("Locate"),
description=_("""Make the adapter a locatable adapter
Located adapter should be used if a non-public permission
is used.
"""),
required=False,
default=False,
)
def _rolledUpFactory(factories):
# This has to be named 'factory', aparently, so as not to confuse
# apidoc :(
def factory(ob):
for f in factories:
ob = f(ob)
return ob
# Store the original factory for documentation
factory.factory = factories[0]
return factory
def adapter(_context, factory, provides=None, for_=None, permission=None,
name='', trusted=False, locate=False):
if for_ is None:
if len(factory) == 1:
for_ = adaptedBy(factory[0])
if for_ is None:
raise TypeError("No for attribute was provided and can't "
"determine what the factory adapts.")
for_ = tuple(for_)
if provides is None:
if len(factory) == 1:
p = list(implementedBy(factory[0]))
if len(p) == 1:
provides = p[0]
if provides is None:
raise TypeError("Missing 'provides' attribute")
if name == '':
if len(factory) == 1:
name = getName(factory[0])
# Generate a single factory from multiple factories:
factories = factory
if len(factories) == 1:
factory = factories[0]
elif len(factories) < 1:
raise ComponentConfigurationError("No factory specified")
elif len(factories) > 1 and len(for_) != 1:
raise ComponentConfigurationError(
"Can't use multiple factories and multiple for")
else:
factory = _rolledUpFactory(factories)
if permission is not None:
factory = protectedFactory(factory, provides, permission)
# invoke custom adapter factories
if locate or permission is not None or trusted:
factory = securityAdapterFactory(factory, permission, locate, trusted)
_context.action(
discriminator = ('adapter', for_, provides, name),
callable = handler,
args = ('registerAdapter',
factory, for_, provides, name, _context.info),
)
_context.action(
discriminator = None,
callable = provideInterface,
args = ('', provides)
)
if for_:
for iface in for_:
if iface is not None:
_context.action(
discriminator = None,
callable = provideInterface,
args = ('', iface)
)
class ISubscriberDirective(Interface):
"""
Register a subscriber
"""
factory = GlobalObject(
title=_("Subscriber factory"),
description=_("A factory used to create the subscriber instance."),
required=False,
)
handler = GlobalObject(
title=_("Handler"),
description=_("A callable object that handles events."),
required=False,
)
provides = GlobalInterface(
title=_("Interface the component provides"),
description=_("This attribute specifies the interface the adapter"
" instance must provide."),
required=False,
)
for_ = Tokens(
title=_("Interfaces or classes that this subscriber depends on"),
description=_("This should be a list of interfaces or classes"),
required=False,
value_type=GlobalObject(
missing_value = object(),
),
)
permission = Permission(
title=_("Permission"),
description=_("This subscriber is only available, if the"
" principal has this permission."),
required=False,
)
trusted = Bool(
title=_("Trusted"),
description=_("""Make the subscriber a trusted subscriber
Trusted subscribers have unfettered access to the objects they
adapt. If asked to adapt security-proxied objects, then,
rather than getting an unproxied subscriber of security-proxied
objects, you get a security-proxied subscriber of unproxied
objects.
"""),
required=False,
default=False,
)
locate = Bool(
title=_("Locate"),
description=_("""Make the subscriber a locatable subscriber
Located subscribers should be used if a non-public permission
is used.
"""),
required=False,
default=False,
)
_handler = handler
def subscriber(_context, for_=None, factory=None, handler=None, provides=None,
permission=None, trusted=False, locate=False):
if factory is None:
if handler is None:
raise TypeError("No factory or handler provided")
if provides is not None:
raise TypeError("Cannot use handler with provides")
factory = handler
else:
if handler is not None:
raise TypeError("Cannot use handler with factory")
if provides is None:
raise TypeError(
"You must specify a provided interface when registering "
"a factory")
if for_ is None:
for_ = adaptedBy(factory)
if for_ is None:
raise TypeError("No for attribute was provided and can't "
"determine what the factory (or handler) adapts.")
if permission is not None:
factory = protectedFactory(factory, provides, permission)
for_ = tuple(for_)
# invoke custom adapter factories
if locate or permission is not None or trusted:
factory = securityAdapterFactory(factory, permission, locate, trusted)
if handler is not None:
_context.action(
discriminator = None,
callable = _handler,
args = ('registerHandler',
handler, for_, u'', _context.info),
)
else:
_context.action(
discriminator = None,
callable = _handler,
args = ('registerSubscriptionAdapter',
factory, for_, provides, u'', _context.info),
)
if provides is not None:
_context.action(
discriminator = None,
callable = provideInterface,
args = ('', provides)
)
# For each interface, state that the adapter provides that interface.
for iface in for_:
if iface is not None:
_context.action(
discriminator = None,
callable = provideInterface,
args = ('', iface)
)
class IUtilityDirective(IBasicComponentInformation):
"""Register a utility."""
provides = GlobalInterface(
title=_("Provided interface"),
description=_("Interface provided by the utility."),
required=False,
)
name = TextLine(
title=_("Name"),
description=_("Name of the registration. This is used by"
" application code when locating a utility."),
required=False,
)
def utility(_context, provides=None, component=None, factory=None,
permission=None, name=''):
if factory and component:
raise TypeError("Can't specify factory and component.")
if provides is None:
if factory:
provides = list(implementedBy(factory))
else:
provides = list(providedBy(component))
if len(provides) == 1:
provides = provides[0]
else:
raise TypeError("Missing 'provides' attribute")
if name == '':
if factory:
name = getName(factory)
else:
name = getName(component)
if permission is not None:
component = proxify(component, provides=provides, permission=permission)
_context.action(
discriminator = ('utility', provides, name),
callable = handler,
args = ('registerUtility', component, provides, name, _context.info),
kw = dict(factory=factory),
)
_context.action(
discriminator = None,
callable = provideInterface,
args = ('', provides),
)
class IInterfaceDirective(Interface):
"""
Define an interface
"""
interface = GlobalInterface(
title=_("Interface"),
required=True,
)
type = GlobalInterface(
title=_("Interface type"),
required=False,
)
name = TextLine(
title=_("Name"),
required=False,
)
def interface(_context, interface, type=None, name=''):
_context.action(
discriminator = None,
callable = provideInterface,
args = (name, interface, type)
)
class IBasicViewInformation(Interface):
"""This is the basic information for all views."""
for_ = Tokens(
title=_("Specifications of the objects to be viewed"),
description=_("""This should be a list of interfaces or classes
"""),
required=True,
value_type=GlobalObject(
missing_value=object(),
),
)
permission = Permission(
title=_("Permission"),
description=_("The permission needed to use the view."),
required=False,
)
class_ = GlobalObject(
title=_("Class"),
description=_("A class that provides attributes used by the view."),
required=False,
)
allowed_interface = Tokens(
title=_("Interface that is also allowed if user has permission."),
description=_("""
By default, 'permission' only applies to viewing the view and
any possible sub views. By specifying this attribute, you can
make the permission also apply to everything described in the
supplied interface.
Multiple interfaces can be provided, separated by
whitespace."""),
required=False,
value_type=GlobalInterface(),
)
allowed_attributes = Tokens(
title=_("View attributes that are also allowed if the user"
" has permission."),
description=_("""
By default, 'permission' only applies to viewing the view and
any possible sub views. By specifying 'allowed_attributes',
you can make the permission also apply to the extra attributes
on the view object."""),
required=False,
value_type=PythonIdentifier(),
)
class IBasicResourceInformation(Interface):
"""
Basic information for resources
"""
name = TextLine(
title=_("The name of the resource."),
description=_("The name shows up in URLs/paths. For example 'foo'."),
required=True,
default=u'',
)
provides = GlobalInterface(
title=_("The interface this component provides."),
description=_("""
A view can provide an interface. This would be used for
views that support other views."""),
required=False,
default=Interface,
)
type = GlobalInterface(
title=_("Request type"),
required=True
)
class IViewDirective(IBasicViewInformation, IBasicResourceInformation):
"""Register a view for a component"""
factory = Tokens(
title=_("Factory"),
required=False,
value_type=GlobalObject(),
)
def view(_context, factory, type, name, for_,
permission=None,
allowed_interface=None,
allowed_attributes=None,
provides=Interface,
):
if ((allowed_attributes or allowed_interface)
and (not permission)):
raise ComponentConfigurationError(
"'permission' required with 'allowed_interface' or "
"'allowed_attributes'")
if permission is not None:
checker = _checker(_context, permission,
allowed_interface, allowed_attributes)
class ProxyView(object):
"""Class to create simple proxy views."""
def __init__(self, factory, checker):
self.factory = factory
self.checker = checker
def __call__(self, *objects):
return proxify(self.factory(*objects), self.checker)
factory[-1] = ProxyView(factory[-1], checker)
if not for_:
raise ComponentConfigurationError("No for interfaces specified");
for_ = tuple(for_)
# Generate a single factory from multiple factories:
factories = factory
if len(factories) == 1:
factory = factories[0]
elif len(factories) < 1:
raise ComponentConfigurationError("No view factory specified")
elif len(factories) > 1 and len(for_) > 1:
raise ComponentConfigurationError(
"Can't use multiple factories and multiple for")
else:
def factory(ob, request):
for f in factories[:-1]:
ob = f(ob)
return factories[-1](ob, request)
factory.factory = factories[0]
for_ = for_ + (type,)
_context.action(
discriminator = ('view', for_, name, provides),
callable = handler,
args = ('registerAdapter',
factory, for_, provides, name, _context.info),
)
_context.action(
discriminator = None,
callable = provideInterface,
args = ('', provides)
)
if for_ is not None:
for iface in for_:
if iface is not None:
_context.action(
discriminator = None,
callable = provideInterface,
args = ('', iface)
)
class IResourceDirective(IBasicComponentInformation,
IBasicResourceInformation):
"""Register a resource"""
allowed_interface = Tokens(
title=_("Interface that is also allowed if user has permission."),
required=False,
value_type=GlobalInterface(),
)
allowed_attributes = Tokens(
title=_("View attributes that are also allowed if user"
" has permission."),
required=False,
value_type=PythonIdentifier(),
)
def resource(_context, factory, type, name,
permission=None,
allowed_interface=None, allowed_attributes=None,
provides=Interface):
if ((allowed_attributes or allowed_interface)
and (not permission)):
raise ComponentConfigurationError(
"Must use name attribute with allowed_interface or "
"allowed_attributes"
)
if permission is not None:
checker = _checker(_context, permission,
allowed_interface, allowed_attributes)
def proxyResource(request, factory=factory, checker=checker):
return proxify(factory(request), checker)
proxyResource.factory = factory
factory = proxyResource
_context.action(
discriminator = ('resource', name, type, provides),
callable = handler,
args = ('registerAdapter',
factory, (type,), provides, name, _context.info))
_context.action(
discriminator = None,
callable = provideInterface,
args = ('', type))
_context.action(
discriminator = None,
callable = provideInterface,
args = ('', provides))
@@ -0,0 +1,22 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Zope configuration support
Software that wants to provide new config directives calls
zope.configuration.meta.register.
"""
def namespace(suffix):
return 'http://namespaces.zope.org/'+suffix
@@ -0,0 +1,44 @@
##############################################################################
#
# Copyright (c) 2012 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.
#
##############################################################################
import sys
PY3 = sys.version_info[0] >= 3
if PY3: # pragma: no cover
import builtins
string_types = (str,)
text_type = str
# borrowed from 'six'
def reraise(tp, value, tb=None):
if value is None:
value = tp
if value.__traceback__ is not tb:
raise value.with_traceback(tb)
raise value
else: # pragma: no cover
import __builtin__ as builtins
text_type = unicode
string_types = (basestring,)
# borrowed from 'six'
exec("""\
def reraise(tp, value, tb=None):
raise tp, value, tb
""")
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,97 @@
##############################################################################
#
# Copyright (c) 2004 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.
#
##############################################################################
"""Helper Utility to wrap a text to a set width of characters
"""
__docformat__ = 'restructuredtext'
import re
__all__ = [
'wrap',
'makeDocStructures',
]
para_sep = re.compile('\n{2,}')
whitespace = re.compile('[ \t\n\r]+')
def wrap(text, width=78, indent=0):
"""
Makes sure that we keep a line length of a certain width.
Examples:
>>> from zope.configuration.docutils import wrap
>>> print(wrap('foo bar')[:-2])
foo bar
>>> print(wrap('foo bar', indent=2)[:-2])
foo bar
>>> print(wrap('foo bar, more foo bar', 10)[:-2])
foo bar,
more foo
bar
>>> print(wrap('foo bar, more foo bar', 10, 2)[:-2])
foo bar,
more foo
bar
"""
paras = para_sep.split(text.strip())
new_paras = []
for par in paras:
words = filter(None, whitespace.split(par))
lines = []
line = []
length = indent
for word in words:
if length + len(word) <= width:
line.append(word)
length += len(word) + 1
else:
lines.append(' '*indent + ' '.join(line))
line = [word]
length = len(word) + 1 + indent
lines.append(' '*indent + ' '.join(line))
new_paras.append('\n'.join(lines))
return '\n\n'.join(new_paras) + '\n\n'
def makeDocStructures(context):
"""
makeDocStructures(context) -> namespaces, subdirs
Creates two structures that provide a friendly format for
documentation.
*namespaces* is a dictionary that maps namespaces to a directives
dictionary with the key being the name of the directive and the
value is a tuple: (schema, handler, info).
*subdirs* maps a (namespace, name) pair to a list of subdirectives
that have the form (namespace, name, schema, info).
"""
namespaces = {}
subdirs = {}
registry = context._docRegistry
for (namespace, name), schema, usedIn, handler, info, parent in registry:
if not parent:
ns_entry = namespaces.setdefault(namespace, {})
ns_entry[name] = (schema, handler, info)
else:
sd_entry = subdirs.setdefault((parent.namespace, parent.name), [])
sd_entry.append((namespace, name, schema, handler, info))
return namespaces, subdirs
@@ -0,0 +1,70 @@
##############################################################################
#
# Copyright (c) 2002 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.
#
##############################################################################
"""Standard configuration errors
"""
import traceback
__all__ = [
'ConfigurationError',
]
class ConfigurationError(Exception):
"""There was an error in a configuration
"""
# A list of strings or things that can be converted to strings,
# added by append_details as we walk back up the call/include stack.
# We will print them in reverse order so that the most recent detail is
# last.
_details = ()
def add_details(self, info):
if isinstance(info, BaseException):
info = traceback.format_exception_only(type(info), info)
# Trim trailing newline
info[-1] = info[-1].rstrip()
self._details += tuple(info)
else:
self._details += (info,)
return self
def _with_details(self, opening, detail_formatter):
lines = [' ' + detail_formatter(detail) for detail in self._details]
lines.append(opening)
lines.reverse()
return '\n'.join(lines)
def __str__(self):
s = super(ConfigurationError, self).__str__()
return self._with_details(s, str)
def __repr__(self):
s = super(ConfigurationError, self).__repr__()
return self._with_details(s, repr)
class ConfigurationWrapperError(ConfigurationError):
USE_INFO_REPR = False
def __init__(self, info, exception):
super(ConfigurationWrapperError, self).__init__(repr(info) if self.USE_INFO_REPR else info)
self.add_details(exception)
# This stuff is undocumented and not used but we store
# for backwards compatibility
self.info = info
self.etype = type(exception)
self.evalue = exception
@@ -0,0 +1,570 @@
##############################################################################
#
# Copyright (c) 2003 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.
#
##############################################################################
"""Configuration-specific schema fields
"""
import os
import sys
import warnings
from zope.interface import implementer
from zope.schema import Bool as schema_Bool
from zope.schema import DottedName
from zope.schema import Field
from zope.schema import InterfaceField
from zope.schema import List
from zope.schema import PythonIdentifier as schema_PythonIdentifier
from zope.schema import Text
from zope.schema import ValidationError
from zope.schema.interfaces import IFromUnicode
from zope.schema.interfaces import InvalidValue
from zope.configuration.exceptions import ConfigurationError
from zope.configuration.interfaces import InvalidToken
__all__ = [
'Bool',
'GlobalObject',
'GlobalInterface',
'MessageID',
'Path',
'PythonIdentifier',
'Tokens',
]
class PythonIdentifier(schema_PythonIdentifier):
r"""
This class is like `zope.schema.PythonIdentifier`.
Let's look at an example:
>>> from zope.configuration.fields import PythonIdentifier
>>> class FauxContext(object):
... pass
>>> context = FauxContext()
>>> field = PythonIdentifier().bind(context)
Let's test the fromUnicode method:
>>> field.fromUnicode(u'foo')
'foo'
>>> field.fromUnicode(u'foo3')
'foo3'
>>> field.fromUnicode(u'_foo3')
'_foo3'
Now let's see whether validation works alright
>>> for value in (u'foo', u'foo3', u'foo_', u'_foo3', u'foo_3', u'foo3_'):
... _ = field.fromUnicode(value)
>>> from zope.schema import ValidationError
>>> for value in (u'3foo', u'foo:', u'\\', u''):
... try:
... field.fromUnicode(value)
... except ValidationError:
... print('Validation Error ' + repr(value))
Validation Error '3foo'
Validation Error 'foo:'
Validation Error '\\'
Validation Error ''
.. versionchanged:: 4.2.0
Extend `zope.schema.PythonIdentifier`, which implies that `fromUnicode`
validates the strings.
"""
def _validate(self, value):
super(PythonIdentifier, self)._validate(value)
if not value:
raise ValidationError(value).with_field_and_value(self, value)
@implementer(IFromUnicode)
class GlobalObject(Field):
"""
An object that can be accessed as a module global.
The special value ``*`` indicates a value of `None`; this is
not validated against the *value_type*.
"""
_DOT_VALIDATOR = DottedName()
def __init__(self, value_type=None, **kw):
self.value_type = value_type
super(GlobalObject, self).__init__(**kw)
def _validate(self, value):
super(GlobalObject, self)._validate(value)
if self.value_type is not None:
self.value_type.validate(value)
def fromUnicode(self, value):
r"""
Find and return the module global at the path *value*.
>>> d = {'x': 1, 'y': 42, 'z': 'zope'}
>>> class fakeresolver(dict):
... def resolve(self, n):
... return self[n]
>>> fake = fakeresolver(d)
>>> from zope.schema import Int
>>> from zope.configuration.fields import GlobalObject
>>> g = GlobalObject(value_type=Int())
>>> gg = g.bind(fake)
>>> gg.fromUnicode("x")
1
>>> gg.fromUnicode(" x \n ")
1
>>> gg.fromUnicode("y")
42
>>> gg.fromUnicode("z")
Traceback (most recent call last):
...
WrongType: ('zope', (<type 'int'>, <type 'long'>), '')
>>> g = GlobalObject(constraint=lambda x: x%2 == 0)
>>> gg = g.bind(fake)
>>> gg.fromUnicode("x")
Traceback (most recent call last):
...
ConstraintNotSatisfied: 1
>>> gg.fromUnicode("y")
42
>>> g = GlobalObject()
>>> gg = g.bind(fake)
>>> print(gg.fromUnicode('*'))
None
"""
name = str(value.strip())
# special case, mostly for interfaces
if name == '*':
return None
try:
# Leading dots are allowed here to indicate current
# package, but not accepted by DottedName. Take care,
# though, because a single dot is valid to resolve, but
# not valid to pass to DottedName (as an empty string)
to_validate = name.lstrip('.')
if to_validate:
self._DOT_VALIDATOR.validate(to_validate)
except ValidationError as v:
v.with_field_and_value(self, name)
raise
try:
value = self.context.resolve(name)
except ConfigurationError as v:
raise ValidationError(v).with_field_and_value(self, name)
self.validate(value)
return value
@implementer(IFromUnicode)
class GlobalInterface(GlobalObject):
"""
An interface that can be accessed from a module.
Example:
First, we need to set up a stub name resolver:
>>> from zope.interface import Interface
>>> class IFoo(Interface):
... pass
>>> class Foo(object):
... pass
>>> d = {'Foo': Foo, 'IFoo': IFoo}
>>> class fakeresolver(dict):
... def resolve(self, n):
... return self[n]
>>> fake = fakeresolver(d)
Now verify constraints are checked correctly:
>>> from zope.configuration.fields import GlobalInterface
>>> g = GlobalInterface()
>>> gg = g.bind(fake)
>>> gg.fromUnicode('IFoo') is IFoo
True
>>> gg.fromUnicode(' IFoo ') is IFoo
True
>>> gg.fromUnicode('Foo')
Traceback (most recent call last):
...
NotAnInterface: (<class 'Foo'>, ...
"""
def __init__(self, **kw):
super(GlobalInterface, self).__init__(InterfaceField(), **kw)
@implementer(IFromUnicode)
class Tokens(List):
"""
A list that can be read from a space-separated string.
"""
def fromUnicode(self, value):
r"""
Split the input string and convert it to *value_type*.
Consider GlobalObject tokens:
First, we need to set up a stub name resolver:
>>> d = {'x': 1, 'y': 42, 'z': 'zope', 'x.y.x': 'foo'}
>>> class fakeresolver(dict):
... def resolve(self, n):
... return self[n]
>>> fake = fakeresolver(d)
>>> from zope.configuration.fields import Tokens
>>> from zope.configuration.fields import GlobalObject
>>> g = Tokens(value_type=GlobalObject())
>>> gg = g.bind(fake)
>>> gg.fromUnicode(" \n x y z \n")
[1, 42, 'zope']
>>> from zope.schema import Int
>>> g = Tokens(value_type=
... GlobalObject(value_type=
... Int(constraint=lambda x: x%2 == 0)))
>>> gg = g.bind(fake)
>>> gg.fromUnicode("x y")
Traceback (most recent call last):
...
InvalidToken: 1 in x y
>>> gg.fromUnicode("z y")
Traceback (most recent call last):
...
InvalidToken: ('zope', (<type 'int'>, <type 'long'>), '') in z y
>>> gg.fromUnicode("y y")
[42, 42]
"""
value = value.strip()
if value:
vt = self.value_type.bind(self.context)
values = []
for s in value.split():
try:
v = vt.fromUnicode(s)
except ValidationError as ex:
raise InvalidToken("%s in %r" % (ex, value)).with_field_and_value(self, s)
else:
values.append(v)
else:
values = []
self.validate(values)
return values
class PathProcessor(object):
# Internal helper for manipulations on paths
@classmethod
def expand(cls, filename):
# Perform the expansions we want to have done. Returns a
# tuple: (path, needs_processing) If the second value is true,
# further processing should be done (the path isn't fully
# resolved); if false, the path should be used as is
filename = filename.strip()
# expanding a ~ at the front should generally result
# in an absolute path.
filename = os.path.expanduser(filename)
filename = os.path.expandvars(filename)
if os.path.isabs(filename):
return os.path.normpath(filename), False
return filename, True
@implementer(IFromUnicode)
class Path(Text):
"""
A file path name, which may be input as a relative path
Input paths are converted to absolute paths and normalized.
"""
def fromUnicode(self, value):
r"""
Convert the input path to a normalized, absolute path.
Let's look at an example:
First, we need a "context" for the field that has a path
function for converting relative path to an absolute path.
We'll be careful to do this in an operating system independent fashion.
>>> from zope.configuration.fields import Path
>>> class FauxContext(object):
... def path(self, p):
... return os.path.join(os.sep, 'faux', 'context', p)
>>> context = FauxContext()
>>> field = Path().bind(context)
Lets try an absolute path first:
>>> import os
>>> p = os.path.join(os.sep, u'a', u'b')
>>> n = field.fromUnicode(p)
>>> n.split(os.sep)
['', 'a', 'b']
This should also work with extra spaces around the path:
>>> p = " \n %s \n\n " % p
>>> n = field.fromUnicode(p)
>>> n.split(os.sep)
['', 'a', 'b']
Environment variables are expanded:
>>> os.environ['path-test'] = '42'
>>> with_env = os.path.join(os.sep, u'a', u'${path-test}')
>>> n = field.fromUnicode(with_env)
>>> n.split(os.sep)
['', 'a', '42']
Now try a relative path:
>>> p = os.path.join(u'a', u'b')
>>> n = field.fromUnicode(p)
>>> n.split(os.sep)
['', 'faux', 'context', 'a', 'b']
The current user is expanded (these are implicitly relative paths):
>>> old_home = os.environ.get('HOME')
>>> os.environ['HOME'] = os.path.join(os.sep, 'HOME')
>>> n = field.fromUnicode('~')
>>> n.split(os.sep)
['', 'HOME']
>>> if old_home:
... os.environ['HOME'] = old_home
... else:
... del os.environ['HOME']
.. versionchanged:: 4.2.0
Start expanding home directories and environment variables.
"""
filename, needs_processing = PathProcessor.expand(value)
if needs_processing:
filename = self.context.path(filename)
return filename
@implementer(IFromUnicode)
class Bool(schema_Bool):
"""
A boolean value.
Values may be input (in upper or lower case) as any of:
- yes / no
- y / n
- true / false
- t / f
.. caution::
Do not confuse this with :class:`zope.schema.Bool`.
That class will only parse ``"True"`` and ``"true"`` as
`True` values. Any other value will silently be accepted as
`False`. This class raises a validation error for unrecognized
input.
"""
def fromUnicode(self, value):
"""
Convert the input string to a boolean.
Example:
>>> from zope.configuration.fields import Bool
>>> Bool().fromUnicode(u"yes")
True
>>> Bool().fromUnicode(u"y")
True
>>> Bool().fromUnicode(u"true")
True
>>> Bool().fromUnicode(u"no")
False
>>> Bool().fromUnicode(u"surprise")
Traceback (most recent call last):
...
zope.schema._bootstrapinterfaces.InvalidValue
"""
value = value.lower()
if value in ('1', 'true', 'yes', 't', 'y'):
return True
if value in ('0', 'false', 'no', 'f', 'n'):
return False
# Unlike the superclass, anything else is invalid.
raise InvalidValue().with_field_and_value(self, value)
@implementer(IFromUnicode)
class MessageID(Text):
"""
Text string that should be translated.
When a string is converted to a message ID, it is also recorded in
the context.
"""
__factories = {}
def fromUnicode(self, u):
"""
Translate a string to a MessageID.
>>> from zope.configuration.fields import MessageID
>>> class Info(object):
... file = 'file location'
... line = 8
>>> class FauxContext(object):
... i18n_strings = {}
... info = Info()
>>> context = FauxContext()
>>> field = MessageID().bind(context)
There is a fallback domain when no domain has been specified.
Exchange the warn function so we can make test whether the warning
has been issued
>>> warned = None
>>> def fakewarn(*args, **kw):
... global warned
... warned = args
>>> import warnings
>>> realwarn = warnings.warn
>>> warnings.warn = fakewarn
>>> i = field.fromUnicode(u"Hello world!")
>>> i
'Hello world!'
>>> i.domain
'untranslated'
>>> warned
("You did not specify an i18n translation domain for the '' field in file location",)
>>> warnings.warn = realwarn
With the domain specified:
>>> context.i18n_strings = {}
>>> context.i18n_domain = 'testing'
We can get a message id:
>>> i = field.fromUnicode(u"Hello world!")
>>> i
'Hello world!'
>>> i.domain
'testing'
In addition, the string has been registered with the context:
>>> context.i18n_strings
{'testing': {'Hello world!': [('file location', 8)]}}
>>> i = field.fromUnicode(u"Foo Bar")
>>> i = field.fromUnicode(u"Hello world!")
>>> from pprint import PrettyPrinter
>>> pprint=PrettyPrinter(width=70).pprint
>>> pprint(context.i18n_strings)
{'testing': {'Foo Bar': [('file location', 8)],
'Hello world!': [('file location', 8),
('file location', 8)]}}
>>> from zope.i18nmessageid import Message
>>> isinstance(list(context.i18n_strings['testing'].keys())[0], Message)
True
Explicit Message IDs
>>> i = field.fromUnicode(u'[View-Permission] View')
>>> i
'View-Permission'
>>> i.default
'View'
>>> i = field.fromUnicode(u'[] [Some] text')
>>> i
'[Some] text'
>>> i.default is None
True
"""
context = self.context
domain = getattr(context, 'i18n_domain', '')
if not domain:
domain = 'untranslated'
warnings.warn(
"You did not specify an i18n translation domain for the "\
"'%s' field in %s" % (self.getName(), context.info.file)
)
if not isinstance(domain, str):
# IZopeConfigure specifies i18n_domain as a BytesLine, but that's
# wrong on Python 3, where the filesystem uses str, and hence
# zope.i18n registers ITranslationDomain utilities with str names.
# If we keep bytes, we can't find those utilities.
enc = sys.getfilesystemencoding() or sys.getdefaultencoding()
domain = domain.decode(enc)
v = super(MessageID, self).fromUnicode(u)
# Check whether there is an explicit message is specified
default = None
if v.startswith('[]'):
v = v[2:].lstrip()
elif v.startswith('['):
end = v.find(']')
default = v[end+2:]
v = v[1:end]
# Convert to a message id, importing the factory, if necessary
factory = self.__factories.get(domain)
if factory is None:
import zope.i18nmessageid
factory = zope.i18nmessageid.MessageFactory(domain)
self.__factories[domain] = factory
msgid = factory(v, default)
# Record the string we got for the domain
i18n_strings = context.i18n_strings
strings = i18n_strings.get(domain)
if strings is None:
strings = i18n_strings[domain] = {}
locations = strings.setdefault(msgid, [])
locations.append((context.info.file, context.info.line))
return msgid
@@ -0,0 +1,137 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Zope Configuration (ZCML) interfaces
"""
from zope.interface import Interface
from zope.schema import BytesLine
from zope.schema.interfaces import ValidationError
__all__ = [
'InvalidToken',
'IConfigurationContext',
'IGroupingContext',
]
class InvalidToken(ValidationError):
"""Invaid token in list."""
class IConfigurationContext(Interface):
"""Configuration Context
The configuration context manages information about the state of
the configuration system, such as the package containing the
configuration file. More importantly, it provides methods for
importing objects and opening files relative to the package.
"""
package = BytesLine(
title=(u"The current package name"),
description=(u"""\
This is the name of the package containing the configuration
file being executed. If the configuration file was not
included by package, then this is None.
"""),
required=False,
)
def resolve(dottedname):
"""Resolve a dotted name to an object
A dotted name is constructed by concatenating a dotted module
name with a global name within the module using a dot. For
example, the object named "spam" in the foo.bar module has a
dotted name of foo.bar.spam. If the current package is a
prefix of a dotted name, then the package name can be relaced
with a leading dot, So, for example, if the configuration file
is in the foo package, then the dotted name foo.bar.spam can
be shortened to .bar.spam.
If the current package is multiple levels deep, multiple
leading dots can be used to refer to higher-level modules.
For example, if the current package is x.y.z, the dotted
object name ..foo refers to x.y.foo.
"""
def path(filename):
"""Compute a full file name for the given file
If the filename is relative to the package, then the returned
name will include the package path, otherwise, the original
file name is returned.
Environment variables in the path are expanded, and if the path
begins with the username marker (~), that is expanded as well.
.. versionchanged:: 4.2.0
Start expanding home directories and environment variables.
"""
def checkDuplicate(filename):
"""Check for duplicate imports of the same file.
Raises an exception if this file had been processed before. This
is better than an unlimited number of conflict errors.
"""
def processFile(filename):
"""Check whether a file needs to be processed.
Return True if processing is needed and False otherwise. If
the file needs to be processed, it will be marked as
processed, assuming that the caller will procces the file if
it needs to be procssed.
"""
def action(discriminator, callable, args=(), kw={}, order=0,
includepath=None, info=None):
"""Record a configuration action
The job of most directives is to compute actions for later
processing. The action method is used to record those actions.
:param callable: The object to call to implement the action.
:param tuple args: Arguments to pass to *callable*
:param dict kw: Keyword arguments to pass to *callable*
:param object discriminator: Used to to find actions that conflict.
Actions conflict if they have equal discriminators. The
exception to this is the special case of the discriminator
with the value `None`. An action with a discriminator of `None`
never conflicts with other actions.
:keyword int order: This is possible to add an order argument to crudely control
the order of execution.
:keyword str info: Optional source line information
:keyword includepath: is None (the default) or a tuple of
include paths for this action.
"""
def provideFeature(name):
"""Record that a named feature is available in this context."""
def hasFeature(name):
"""Check whether a named feature is available in this context."""
class IGroupingContext(Interface):
def before():
"""Do something before processing nested directives
"""
def after():
"""Do something after processing nested directives
"""
@@ -0,0 +1,98 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""
Provide configuration object name resolution.
.. note:: This module is no longer used by `zope.configuration` and
may be deprecated soon. Its functions are not documented.
"""
import os
from types import ModuleType
__all__ = [
'resolve',
'getNormalizedName',
'path',
]
def resolve(name, package='zopeproducts', _silly=('__doc__',), _globals={}):
name = name.strip()
if name.startswith('.'):
name = package + name
if name.endswith('.') or name.endswith('+'):
name = name[:-1]
repeat = True
else:
repeat = False
names = name.split('.')
last = names[-1]
mod = '.'.join(names[:-1])
if not mod:
return __import__(name, _globals, _globals, _silly)
while 1:
m = __import__(mod, _globals, _globals, _silly)
try:
a = getattr(m, last)
except AttributeError:
if not repeat:
return __import__(name, _globals, _globals, _silly)
else:
if not repeat or (not isinstance(a, ModuleType)):
return a
mod += '.' + last
def getNormalizedName(name, package):
name = name.strip()
if name.startswith('.'):
name = package + name
if name.endswith('.') or name.endswith('+'):
name = name[:-1]
repeat = True
else:
repeat = False
name = name.split(".")
while len(name) > 1 and name[-1] == name[-2]:
name.pop()
repeat = 1
name = ".".join(name)
if repeat:
name += "+"
return name
def path(file='', package='zopeproducts', _silly=('__doc__',), _globals={}):
# XXX WTF? why not look for abspath before importing?
try:
package = __import__(package, _globals, _globals, _silly)
except ImportError:
norm = os.path.normpath(file)
if file and os.path.abspath(norm) == norm:
# The package didn't matter
return norm
raise
path = os.path.dirname(package.__file__)
if file:
path = os.path.join(path, file)
return path
@@ -0,0 +1,2 @@
#
# This file is necessary to make this directory a package.
@@ -0,0 +1,3 @@
# I'm bad. I want to be bad. Don't try to change me.
raise ImportError()
@@ -0,0 +1,35 @@
##############################################################################
#
# Copyright (c) 2003 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.
#
##############################################################################
""" Enable "Making specific directives condition" section of narrative docs.
"""
from zope.interface import Interface
from zope.schema import Id
class IRegister(Interface):
"""Trivial sample registry."""
id = Id(
title=u"Identifier",
description=u"Some identifier that can be checked.",
required=True,
)
registry = []
def register(context, id):
context.action(discriminator=('Register', id),
callable=registry.append,
args=(id,)
)
@@ -0,0 +1,78 @@
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:meta="http://namespaces.zope.org/meta"
xmlns:test="http://sample.namespaces.zope.org/test"
xmlns:zcml="http://namespaces.zope.org/zcml"
>
<meta:directive
name="register"
namespace="http://sample.namespaces.zope.org/test"
schema=".conditions.IRegister"
handler=".conditions.register"
>
This registers a directive which creates registrations we can test.
</meta:directive>
<test:register id="unqualified.registration" />
<meta:provides feature="testfeature" />
<meta:provides feature="anothertestfeature" />
<configure zcml:condition="have testfeature">
ZCML directives inside here should be included.
<configure>
<test:register id="nested.true.condition" />
</configure>
<!-- These registrations stand on the basis of their own
conditions: -->
<test:register
zcml:condition="have anothertestfeature"
id="true.condition.nested.in.true"
/>
<test:register
zcml:condition="have undefinedfeature"
id="false.condition.nested.in.true"
/>
</configure>
<test:register
zcml:condition="have testfeature"
id="direct.true.condition"
>
This registration should be included.
</test:register>
<configure zcml:condition="have undefinedfeature">
ZCML directives inside here should be ignored.
<configure>
<test:register id="nested.false.condition" />
</configure>
<!-- These registrations are ignored, since the container is
ignored: -->
<test:register
zcml:condition="have testfeature"
id="true.condition.nested.in.false"
/>
<test:register
zcml:condition="have undefinedfeature"
id="false.condition.nested.in.false"
/>
</configure>
<test:register
zcml:condition="have undefinedfeature"
id="direct.false.condition"
>
This registration should be ignored.
</test:register>
</configure>
@@ -0,0 +1,87 @@
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Test directives
"""
from zope.interface import Interface
from zope.interface import implementer
from zope.schema import NativeStringLine
from zope.schema import Text
from zope.configuration.config import GroupingContextDecorator
from zope.configuration.interfaces import IConfigurationContext
from zope.configuration.fields import GlobalObject
class F(object):
def __repr__(self):
return 'f'
def __call__(self, *a, **k):
raise NotImplementedError
f = F()
class ISimple(Interface):
a = Text()
b = Text(required=False)
c = NativeStringLine()
def simple(context, a=None, c=None, b=u"xxx"):
return [(('simple', a, b, c), f, (a, b, c))]
def newsimple(context, a, c, b=u"xxx"):
context.action(('newsimple', a, b, c), f, (a, b, c))
class IPackaged(Interface):
package = GlobalObject()
class IPackagedContext(IPackaged, IConfigurationContext):
pass
@implementer(IPackagedContext)
class Packaged(GroupingContextDecorator):
pass
class IFactory(Interface):
factory = GlobalObject()
def factory(context, factory):
context.action(('factory', 1,2), factory)
class Complex(object):
def __init__(self, context, a, c, b=u"xxx"):
self.a, self.b, self.c = a, b, c
context.action("Complex.__init__")
def factory(self, context, factory):
return [(('Complex.factory', 1, 2), factory, (self.a, ))]
def __call__(self):
return [(('Complex', 1,2), f, (self.b, self.c))]
class Ik(Interface):
for_ = NativeStringLine()
class_ = NativeStringLine()
x = NativeStringLine()
def k(context, for_, class_, x):
context.action(('k', for_), f, (for_, class_, x))
@@ -0,0 +1,6 @@
<configure>
<include package=".sub" />
<include file="spam.zcml" />
</configure>

Some files were not shown because too many files have changed in this diff Show More