[z3-checkins] r18340 - in z3/Five/branch/regebro-sitemanager: .
browser doc form/tests testing tests
regebro at codespeak.net
regebro at codespeak.net
Mon Oct 10 16:25:09 CEST 2005
Author: regebro
Date: Mon Oct 10 16:25:00 2005
New Revision: 18340
Added:
z3/Five/branch/regebro-sitemanager/localsite.py
- copied unchanged from r18259, z3/Five/branch/castle-local-sitemanager/localsite.py
z3/Five/branch/regebro-sitemanager/localsite.zcml
- copied unchanged from r18259, z3/Five/branch/castle-local-sitemanager/localsite.zcml
z3/Five/branch/regebro-sitemanager/testing/interfaces.py
- copied unchanged from r18259, z3/Five/branch/castle-local-sitemanager/testing/interfaces.py
z3/Five/branch/regebro-sitemanager/testing/localsite.py
- copied unchanged from r18259, z3/Five/branch/castle-local-sitemanager/testing/localsite.py
z3/Five/branch/regebro-sitemanager/tests/test_localservice.py
- copied unchanged from r18259, z3/Five/branch/castle-local-sitemanager/tests/test_localservice.py
Modified:
z3/Five/branch/regebro-sitemanager/browser/TrustedExpression.py
z3/Five/branch/regebro-sitemanager/configure.zcml
z3/Five/branch/regebro-sitemanager/doc/features.txt
z3/Five/branch/regebro-sitemanager/fiveconfigure.py
z3/Five/branch/regebro-sitemanager/fivedirectives.py
z3/Five/branch/regebro-sitemanager/form/tests/forms.txt
z3/Five/branch/regebro-sitemanager/interfaces.py
z3/Five/branch/regebro-sitemanager/meta.zcml
z3/Five/branch/regebro-sitemanager/monkey.py
Log:
Merging from the castle branch.
Modified: z3/Five/branch/regebro-sitemanager/browser/TrustedExpression.py
==============================================================================
--- z3/Five/branch/regebro-sitemanager/browser/TrustedExpression.py (original)
+++ z3/Five/branch/regebro-sitemanager/browser/TrustedExpression.py Mon Oct 10 16:25:00 2005
@@ -70,7 +70,7 @@
o = get(object, name, M)
if o is M:
try: o = object[name]
- except AttributeError: # better exception
+ except (AttributeError, TypeError): # better exception
raise AttributeError(name)
object = o
Modified: z3/Five/branch/regebro-sitemanager/configure.zcml
==============================================================================
--- z3/Five/branch/regebro-sitemanager/configure.zcml (original)
+++ z3/Five/branch/regebro-sitemanager/configure.zcml Mon Oct 10 16:25:00 2005
@@ -6,6 +6,7 @@
<include file="interfaces.zcml" />
<include file="permissions.zcml" />
<include file="i18n.zcml" />
+ <include file="localsite.zcml" />
<include package=".browser" />
<include package=".form" />
<include package=".skin" />
Modified: z3/Five/branch/regebro-sitemanager/doc/features.txt
==============================================================================
--- z3/Five/branch/regebro-sitemanager/doc/features.txt (original)
+++ z3/Five/branch/regebro-sitemanager/doc/features.txt Mon Oct 10 16:25:00 2005
@@ -84,3 +84,23 @@
ignored by views anyway, as they are trusted -- it only serves to
protect directly exposed methods on content classes (the python
scripts and the ZPublisher).
+
+Local Site Manager
+==================
+
+Five can support the concept of a Local Site Manager. The steps for
+creating one are:
+
+ - Register your Zope 2 class with the 'local site hook' using the
+ <five:localsitehook> directive. Doing that will mixin the FiveSite
+ class into your class by means of 'structured monkey patching'.
+
+ - Implement an ``IFiveSite`` adapter for your Zope 2 class. For the full
+ interface definition refer to
+ ``Products.Five.interfaces.IFiveSite``.
+
+ - To enable the Local Site Hook for an instance of your class, use::
+
+ from Products.Five.localsite import enableLocalSiteHook
+ enableLocalSiteHook(obj)
+
Modified: z3/Five/branch/regebro-sitemanager/fiveconfigure.py
==============================================================================
--- z3/Five/branch/regebro-sitemanager/fiveconfigure.py (original)
+++ z3/Five/branch/regebro-sitemanager/fiveconfigure.py Mon Oct 10 16:25:00 2005
@@ -27,6 +27,7 @@
from zope.interface import classImplements
from zope.configuration import xmlconfig
+from zope.configuration.exceptions import ConfigurationError
from zope.app.component.interface import provideInterface
from viewable import Viewable
@@ -55,7 +56,7 @@
# in the control panel. However, all attempts to do so has failed from my
# side. //regebro
exc = sys.exc_info()
- LOG('Five', ERROR, 'Could not import Product %s' % product, error=exc)
+ LOG('Five', ERROR, 'Could not import Product %s' % product.__name__, error=exc)
def loadProducts(_context):
products = findProducts()
@@ -274,3 +275,62 @@
from zope.testing.cleanup import addCleanUp
addCleanUp(cleanUp)
del addCleanUp
+
+from zope.interface.interface import InterfaceClass
+from zope.app.site.interfaces import IPossibleSite, ISite
+from zope.app.component.metaconfigure import adapter
+from zope.app.utility.interfaces import ILocalUtilityService
+from localsite import FiveSite, SimpleLocalUtilityService
+
+def classSiteHook(class_, site_class):
+ setattr(class_, 'getSiteManager',
+ site_class.getSiteManager.im_func)
+ setattr(class_, 'setSiteManager',
+ site_class.setSiteManager.im_func)
+
+count = 0
+def next():
+ global count
+ count += 1
+ return count
+
+def installSiteHook(_context, class_, site_class=None, utility_service=None):
+ if site_class is None:
+ if not IPossibleSite.implementedBy(class_):
+ # This is not a possible site, we need to monkey-patch it so that
+ # it is.
+ site_class = FiveSite
+ else:
+ if not IPossibleSite.implementedBy(site_class):
+ raise ConfigurationError('Site class does not implement '
+ 'IPossibleClass: %s' % site_class)
+ if site_class is not None:
+ _context.action(
+ discriminator = (class_,),
+ callable = classSiteHook,
+ args=(class_, site_class)
+ )
+ _context.action(
+ discriminator = (class_, ISite),
+ callable = classImplements,
+ args=(class_, ISite)
+ )
+ if utility_service is None:
+ utility_service = SimpleLocalUtilityService
+ else:
+ if not ILocalUtilityService.implementedBy(utility_service):
+ raise ConfigurationError('utility_service does not implement '
+ 'ILocalUtilityService: %s' % utility_service)
+
+ # Generate a marker interface that should be unique, so that
+ # we can register the utility service only for this class.
+ iface = InterfaceClass('IFiveSite%s' % next())
+ adapter(_context, factory=(utility_service,),
+ provides=ILocalUtilityService,
+ for_=(iface,))
+ _context.action(
+ discriminator = (class_, 'UtilityMarker'),
+ callable = classImplements,
+ args=(class_, iface)
+ )
+
Modified: z3/Five/branch/regebro-sitemanager/fivedirectives.py
==============================================================================
--- z3/Five/branch/regebro-sitemanager/fivedirectives.py (original)
+++ z3/Five/branch/regebro-sitemanager/fivedirectives.py Mon Oct 10 16:25:00 2005
@@ -104,3 +104,19 @@
description=u"The directory containing the resource data.",
required=True
)
+
+class ISiteDirective(Interface):
+ """Make instances of class hookable for Site.
+
+ site_class is an implementation of ISite, which will have it's methods
+ monkey_patched into the the class. If not given a default implementation
+ will be used.
+ """
+ class_ = GlobalObject(
+ title=u"Class",
+ required=True
+ )
+ site_class = GlobalObject(
+ title=u"Site Class",
+ required=False
+ )
Modified: z3/Five/branch/regebro-sitemanager/form/tests/forms.txt
==============================================================================
--- z3/Five/branch/regebro-sitemanager/form/tests/forms.txt (original)
+++ z3/Five/branch/regebro-sitemanager/form/tests/forms.txt Mon Oct 10 16:25:00 2005
@@ -48,9 +48,8 @@
>>> print http(r"""
... GET /test_folder_1_/ftf/+/protectedaddform.html HTTP/1.1
... """, handle_errors=False)
- Traceback (most recent call last):
+ HTTP/1.1 401 Unauthorized
...
- Unauthorized: ...
Now let's add a piece of our sample content object to test more things
on it:
Modified: z3/Five/branch/regebro-sitemanager/interfaces.py
==============================================================================
--- z3/Five/branch/regebro-sitemanager/interfaces.py (original)
+++ z3/Five/branch/regebro-sitemanager/interfaces.py Mon Oct 10 16:25:00 2005
@@ -17,6 +17,7 @@
"""
from zope.interface import Interface
from zope.interface.interfaces import IInterface
+from zope.app.site.interfaces import ISite
class IBrowserDefault(Interface):
"""Provide a hook for deciding about the default view for an object"""
@@ -34,6 +35,9 @@
menu items.
"""
+class IFiveSite(ISite):
+ """Five specialization of ISite
+ """
#
# BBB: Zope core interfaces
Modified: z3/Five/branch/regebro-sitemanager/meta.zcml
==============================================================================
--- z3/Five/branch/regebro-sitemanager/meta.zcml (original)
+++ z3/Five/branch/regebro-sitemanager/meta.zcml Mon Oct 10 16:25:00 2005
@@ -162,6 +162,12 @@
handler=".fiveconfigure.bridge"
/>
+ <meta:directive
+ name="localsite"
+ schema=".fivedirectives.ISiteDirective"
+ handler=".fiveconfigure.installSiteHook"
+ />
+
</meta:directives>
<meta:directive
Modified: z3/Five/branch/regebro-sitemanager/monkey.py
==============================================================================
--- z3/Five/branch/regebro-sitemanager/monkey.py (original)
+++ z3/Five/branch/regebro-sitemanager/monkey.py Mon Oct 10 16:25:00 2005
@@ -55,3 +55,36 @@
import sys
from Products.Five.bbb import transaction
sys.modules['transaction'] = transaction
+
+ from Acquisition import aq_inner, aq_parent
+ from zope.app.site.interfaces import ISiteManager
+ from zope.component.exceptions import ComponentLookupError
+
+ def getLocalServices(context):
+ """Returns the service manager that contains `context`.
+
+ If `context` is a local service, returns the service manager
+ that contains that service. If `context` is a service manager,
+ returns `context`.
+
+ Otherwise, raises ``ComponentLookupError('Services')``
+
+ XXX Basically, this overrides the one in Zope3 X3.0 so that it
+ uses acquisition instead of looking up __parent__.
+ """
+
+ # IMPORTANT
+ #
+ # This is not allowed to use any services to get its job done!
+
+ while not (context is None or
+ ISiteManager.providedBy(context)):
+ context = aq_parent(aq_inner(context))
+ if context is None:
+ raise ComponentLookupError('Services')
+ else:
+ return context
+
+ from zope.app.component import localservice
+ localservice.getLocalServices = getLocalServices
+
More information about the z3-checkins
mailing list