[z3-checkins] r18543 - in z3/Five/trunk: . browser doc form/tests
testing tests
regebro at codespeak.net
regebro at codespeak.net
Fri Oct 14 15:37:33 CEST 2005
Author: regebro
Date: Fri Oct 14 15:37:26 2005
New Revision: 18543
Added:
z3/Five/trunk/localsite.py
- copied unchanged from r18537, z3/Five/branch/regebro-sitemanager/localsite.py
z3/Five/trunk/localsite.zcml
- copied unchanged from r18537, z3/Five/branch/regebro-sitemanager/localsite.zcml
z3/Five/trunk/testing/interfaces.py
- copied unchanged from r18537, z3/Five/branch/regebro-sitemanager/testing/interfaces.py
z3/Five/trunk/testing/localsite.py
- copied unchanged from r18537, z3/Five/branch/regebro-sitemanager/testing/localsite.py
z3/Five/trunk/tests/test_localservice.py
- copied unchanged from r18537, z3/Five/branch/regebro-sitemanager/tests/test_localservice.py
Modified:
z3/Five/trunk/CHANGES.txt
z3/Five/trunk/browser/TrustedExpression.py
z3/Five/trunk/configure.zcml
z3/Five/trunk/doc/features.txt
z3/Five/trunk/fiveconfigure.py
z3/Five/trunk/fivedirectives.py
z3/Five/trunk/form/tests/forms.txt
z3/Five/trunk/interfaces.py
z3/Five/trunk/meta.zcml
z3/Five/trunk/monkey.py
Log:
Merging local site support into trunk!
Modified: z3/Five/trunk/CHANGES.txt
==============================================================================
--- z3/Five/trunk/CHANGES.txt (original)
+++ z3/Five/trunk/CHANGES.txt Fri Oct 14 15:37:26 2005
@@ -5,6 +5,14 @@
Trunk only
==========
+Features
+--------
+* Local site support: Five has now support for creating local sites and
+ thereby local utilities. This is mostly needed for allowing CMF to convert
+ it's portal tools into local utilities.
+ See doc/local_sites.txt for more information
+ (that is, when I have finished that piece of documentation /Regebro).
+
Restructuring
-------------
Modified: z3/Five/trunk/browser/TrustedExpression.py
==============================================================================
--- z3/Five/trunk/browser/TrustedExpression.py (original)
+++ z3/Five/trunk/browser/TrustedExpression.py Fri Oct 14 15:37:26 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/trunk/configure.zcml
==============================================================================
--- z3/Five/trunk/configure.zcml (original)
+++ z3/Five/trunk/configure.zcml Fri Oct 14 15:37:26 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/trunk/doc/features.txt
==============================================================================
--- z3/Five/trunk/doc/features.txt (original)
+++ z3/Five/trunk/doc/features.txt Fri Oct 14 15:37:26 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/trunk/fiveconfigure.py
==============================================================================
--- z3/Five/trunk/fiveconfigure.py (original)
+++ z3/Five/trunk/fiveconfigure.py Fri Oct 14 15:37:26 2005
@@ -25,14 +25,20 @@
import App
from zLOG import LOG, ERROR
-from zope.interface import classImplements
+from zope.interface import classImplements, classImplementsOnly, implementedBy
+from zope.interface.interface import InterfaceClass
from zope.configuration import xmlconfig
+from zope.configuration.exceptions import ConfigurationError
from zope.app.component.interface import provideInterface
+from zope.app.component.metaconfigure import adapter
+from zope.app.utility.interfaces import ILocalUtilityService
+from zope.app.site.interfaces import IPossibleSite, ISite
from viewable import Viewable
from traversable import Traversable
from bridge import fromZ2Interface
from browser.metaconfigure import page
+from localsite import FiveSite, SimpleLocalUtilityService
debug_mode = App.config.getConfiguration().debug_mode
@@ -55,7 +61,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()
@@ -233,6 +239,60 @@
page(_context, name=name, permission=permission,
layer=layer, for_=for_, template=fname)
+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
+
+_localsite_monkies = []
+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)
+ )
+ _localsite_monkies.append(class_)
+
# clean up code
def killMonkey(class_, name, fallback, attr=None):
@@ -265,12 +325,21 @@
killMonkey(class_, '__browser_default__', '__fallback_default__',
'__five_viewable__')
+def uinstallSiteHook(class_):
+ delattr(class_, 'getSiteManager')
+ delattr(class_, 'setSiteManager')
+ classImplementsOnly(class_, implementedBy(class_)-ISite)
+ _localsite_monkies.remove(class_)
+
def cleanUp():
for class_ in _traversable_monkies:
untraversable(class_)
for class_ in _defaultviewable_monkies:
undefaultViewable(class_)
-
+ for class_ in _localsite_monkies:
+ uinstallSiteHook(class_)
+
from zope.testing.cleanup import addCleanUp
addCleanUp(cleanUp)
del addCleanUp
+
Modified: z3/Five/trunk/fivedirectives.py
==============================================================================
--- z3/Five/trunk/fivedirectives.py (original)
+++ z3/Five/trunk/fivedirectives.py Fri Oct 14 15:37:26 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/trunk/form/tests/forms.txt
==============================================================================
--- z3/Five/trunk/form/tests/forms.txt (original)
+++ z3/Five/trunk/form/tests/forms.txt Fri Oct 14 15:37:26 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/trunk/interfaces.py
==============================================================================
--- z3/Five/trunk/interfaces.py (original)
+++ z3/Five/trunk/interfaces.py Fri Oct 14 15:37:26 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/trunk/meta.zcml
==============================================================================
--- z3/Five/trunk/meta.zcml (original)
+++ z3/Five/trunk/meta.zcml Fri Oct 14 15:37:26 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/trunk/monkey.py
==============================================================================
--- z3/Five/trunk/monkey.py (original)
+++ z3/Five/trunk/monkey.py Fri Oct 14 15:37:26 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