[Checkins] SVN: z3c.mountpoint/trunk/ - made it an egg

Michael Howitz mh at gocept.com
Thu Jul 29 02:52:36 EDT 2010


Log message for revision 115190:
  - made it an egg
  - added a buildout
  - fixed tests to run with current packages and without deprecation warnings
  

Changed:
  A   z3c.mountpoint/trunk/CHANGES.txt
  D   z3c.mountpoint/trunk/README.txt
  D   z3c.mountpoint/trunk/__init__.py
  A   z3c.mountpoint/trunk/bootstrap.py
  D   z3c.mountpoint/trunk/browser.py
  D   z3c.mountpoint/trunk/browser.zcml
  A   z3c.mountpoint/trunk/buildout.cfg
  D   z3c.mountpoint/trunk/configure.zcml
  D   z3c.mountpoint/trunk/connection.py
  D   z3c.mountpoint/trunk/interfaces.py
  D   z3c.mountpoint/trunk/mountpoint.py
  D   z3c.mountpoint/trunk/remoteproxy.py
  A   z3c.mountpoint/trunk/setup.py
  A   z3c.mountpoint/trunk/src/
  A   z3c.mountpoint/trunk/src/z3c/
  A   z3c.mountpoint/trunk/src/z3c/mountpoint/
  A   z3c.mountpoint/trunk/src/z3c/mountpoint/README.txt
  A   z3c.mountpoint/trunk/src/z3c/mountpoint/__init__.py
  A   z3c.mountpoint/trunk/src/z3c/mountpoint/browser.py
  A   z3c.mountpoint/trunk/src/z3c/mountpoint/browser.zcml
  A   z3c.mountpoint/trunk/src/z3c/mountpoint/configure.zcml
  A   z3c.mountpoint/trunk/src/z3c/mountpoint/connection.py
  A   z3c.mountpoint/trunk/src/z3c/mountpoint/interfaces.py
  A   z3c.mountpoint/trunk/src/z3c/mountpoint/mountpoint.py
  A   z3c.mountpoint/trunk/src/z3c/mountpoint/remoteproxy.py
  A   z3c.mountpoint/trunk/src/z3c/mountpoint/tests.py
  D   z3c.mountpoint/trunk/tests.py

-=-
Added: z3c.mountpoint/trunk/CHANGES.txt
===================================================================
--- z3c.mountpoint/trunk/CHANGES.txt	                        (rev 0)
+++ z3c.mountpoint/trunk/CHANGES.txt	2010-07-29 06:52:35 UTC (rev 115190)
@@ -0,0 +1,10 @@
+============
+ Change log
+============
+
+0.1 (unreleased)
+================
+
+* Initial release.
+
+


Property changes on: z3c.mountpoint/trunk/CHANGES.txt
___________________________________________________________________
Added: svn:keywords
   + Id Rev Date
Added: svn:eol-style
   + native

Deleted: z3c.mountpoint/trunk/README.txt
===================================================================
--- z3c.mountpoint/trunk/README.txt	2010-07-29 06:50:08 UTC (rev 115189)
+++ z3c.mountpoint/trunk/README.txt	2010-07-29 06:52:35 UTC (rev 115190)
@@ -1,122 +0,0 @@
-================
-ZODB Mount Point
-================
-
-This package provides a very simple implementation of a mount point for an
-object in another ZODB connection. If you have multiple connections defined in
-your ``zope.conf`` configuration file or multiple databases defined in your
-Python code, you can use this package to mount any object from any database at
-any location of another database.
-
-Let's start by creating two databases in the typical Zope 3 application layout:
-
-  >>> from ZODB.tests.test_storage import MinimalMemoryStorage
-  >>> from ZODB import DB
-  >>> from zope.app.folder import rootFolder, Folder
-  >>> import transaction
-
-  >>> dbmap = {}
-
-  >>> db1 = DB(MinimalMemoryStorage(), database_name='db1', databases=dbmap)
-  >>> conn1 = db1.open()
-  >>> conn1.root()['Application'] = rootFolder()
-
-  >>> db2 = DB(MinimalMemoryStorage(), database_name='db2', databases=dbmap)
-  >>> conn2 = db2.open()
-  >>> conn2.root()['Application'] = rootFolder()
-
-  >>> transaction.commit()
-
-Let's now add a sub-folder to the second database, which will serve as the
-object which we wish to mount:
-
-  >>> conn2.root()['Application']['Folder2-1'] = Folder()
-  >>> transaction.commit()
-
-We can now create a mount point:
-
-  >>> from z3c.mountpoint import mountpoint
-  >>> mountPoint = mountpoint.MountPoint(
-  ...     'db2', objectPath=u'/Folder2-1', objectName=u'F2-1')
-
-The first argument to the constructor is the connection name of the database,
-the second argument is the path to the mounted object within the mounted DB
-and the object name is the name under which the object is mounted.
-
-Now we can add the mount point to the first database:
-
-  >>> conn1.root()['Application']['mp'] = mountPoint
-  >>> transaction.commit()
-
-We can now access the mounted object as follows:
-
-  >>> conn1.root()['Application']['mp'].object
-  <zope.app.folder.folder.Folder object at ...>
-
-Note that the object name is not yet used; it is for traversal only.
-
-
-Traversal
----------
-
-So let's have a look at the traversal next. Before being able to traverse, we
-need to register the special mount point traverser:
-
-  >>> import zope.component
-  >>> zope.component.provideAdapter(mountpoint.MountPointTraverser)
-
-We should now be able to traverse to the mounted object now:
-
-  >>> from zope.publisher.browser import TestRequest
-  >>> req = TestRequest()
-
-  >>> from zope.app.publication.publicationtraverse import PublicationTraverser
-  >>> traverser = PublicationTraverser()
-  >>> traverser.traversePath(req, conn1.root()['Application'], 'mp/F2-1')
-  <zope.app.folder.folder.Folder object at ...>
-
-When we add a new object remotely, it available via the mount point as well:
-
-  >>> conn2.root()['Application']['Folder2-1']['Folder2-1.1'] = Folder()
-  >>> transaction.commit()
-
-  >>> tuple(traverser.traversePath(
-  ...    req, conn1.root()['Application'], 'mp/F2-1').keys())
-  (u'Folder2-1.1',)
-
-Now, by default the objects refer to their original path:
-
-  >>> f211 = traverser.traversePath(
-  ...    req, conn1.root()['Application'], 'mp/F2-1/Folder2-1.1')
-
-  >>> from zope.traversing.browser import absoluteurl
-  >>> absoluteurl.absoluteURL(f211, req)
-  'http://127.0.0.1/Folder2-1/Folder2-1.1'
-
-This package solves that problem by wrapping all object by a special remote
-location proxy and providing a special wrapping traverser for those proxies:
-
-  >>> from z3c.mountpoint import remoteproxy
-  >>> zope.component.provideAdapter(remoteproxy.RemoteLocationProxyTraverser)
-
-  >>> f211 = traverser.traversePath(
-  ...    req, conn1.root()['Application'], 'mp/F2-1/Folder2-1.1')
-  >>> absoluteurl.absoluteURL(f211, req)
-  'http://127.0.0.1/mp/F2-1/Folder2-1.1'
-
-
-Updating the Mount Point
-------------------------
-
-Whenever any attribute on the mount point is modified, the mount object is
-updated. For example, when the object path is changed, the object is adjusted
-as well. This is done with an event subscriber:
-
-  >>> mountPoint.objectPath = u'/Folder2-1/Folder2-1.1'
-
-  >>> modifiedEvent = object()
-  >>> mountpoint.updateMountedObject(mountPoint, modifiedEvent)
-
-  >>> f211 == mountPoint.object
-  True
-

Deleted: z3c.mountpoint/trunk/__init__.py
===================================================================
--- z3c.mountpoint/trunk/__init__.py	2010-07-29 06:50:08 UTC (rev 115189)
+++ z3c.mountpoint/trunk/__init__.py	2010-07-29 06:52:35 UTC (rev 115190)
@@ -1 +0,0 @@
-# Make a package.

Copied: z3c.mountpoint/trunk/bootstrap.py (from rev 114727, zc.buildout/trunk/bootstrap/bootstrap.py)
===================================================================
--- z3c.mountpoint/trunk/bootstrap.py	                        (rev 0)
+++ z3c.mountpoint/trunk/bootstrap.py	2010-07-29 06:52:35 UTC (rev 115190)
@@ -0,0 +1,116 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+"""
+
+import os, shutil, sys, tempfile, urllib2
+from optparse import OptionParser
+
+tmpeggs = tempfile.mkdtemp()
+
+is_jython = sys.platform.startswith('java')
+
+# parsing arguments
+parser = OptionParser()
+parser.add_option("-v", "--version", dest="version",
+                          help="use a specific zc.buildout version")
+parser.add_option("-d", "--distribute",
+                   action="store_true", dest="distribute", default=False,
+                   help="Use Disribute rather than Setuptools.")
+
+parser.add_option("-c", None, action="store", dest="config_file",
+                   help=("Specify the path to the buildout configuration "
+                         "file to be used."))
+
+options, args = parser.parse_args()
+
+# if -c was provided, we push it back into args for buildout' main function
+if options.config_file is not None:
+    args += ['-c', options.config_file]
+
+if options.version is not None:
+    VERSION = '==%s' % options.version
+else:
+    VERSION = ''
+
+USE_DISTRIBUTE = options.distribute
+args = args + ['bootstrap']
+
+try:
+    import pkg_resources
+    import setuptools
+    if not hasattr(pkg_resources, '_distribute'):
+        raise ImportError
+except ImportError:
+    ez = {}
+    if USE_DISTRIBUTE:
+        exec urllib2.urlopen('http://python-distribute.org/distribute_setup.py'
+                         ).read() in ez
+        ez['use_setuptools'](to_dir=tmpeggs, download_delay=0, no_fake=True)
+    else:
+        exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                             ).read() in ez
+        ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+    reload(sys.modules['pkg_resources'])
+    import pkg_resources
+
+if sys.platform == 'win32':
+    def quote(c):
+        if ' ' in c:
+            return '"%s"' % c # work around spawn lamosity on windows
+        else:
+            return c
+else:
+    def quote (c):
+        return c
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+ws  = pkg_resources.working_set
+
+if USE_DISTRIBUTE:
+    requirement = 'distribute'
+else:
+    requirement = 'setuptools'
+
+if is_jython:
+    import subprocess
+
+    assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd',
+           quote(tmpeggs), 'zc.buildout' + VERSION],
+           env=dict(os.environ,
+               PYTHONPATH=
+               ws.find(pkg_resources.Requirement.parse(requirement)).location
+               ),
+           ).wait() == 0
+
+else:
+    assert os.spawnle(
+        os.P_WAIT, sys.executable, quote (sys.executable),
+        '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout' + VERSION,
+        dict(os.environ,
+            PYTHONPATH=
+            ws.find(pkg_resources.Requirement.parse(requirement)).location
+            ),
+        ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout' + VERSION)
+import zc.buildout.buildout
+zc.buildout.buildout.main(args)
+shutil.rmtree(tmpeggs)

Deleted: z3c.mountpoint/trunk/browser.py
===================================================================
--- z3c.mountpoint/trunk/browser.py	2010-07-29 06:50:08 UTC (rev 115189)
+++ z3c.mountpoint/trunk/browser.py	2010-07-29 06:52:35 UTC (rev 115190)
@@ -1,32 +0,0 @@
-##############################################################################
-#
-# 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.
-#
-##############################################################################
-"""Browser code
-
-$Id$
-"""
-__docformat__ = "reStructuredText"
-from zope.app.publisher.browser import menu, menumeta
-from zope.security.checker import CheckerPublic
-
-from z3c.mountpoint import interfaces
-
-def ObjectMenuItem(context, request):
-    factory = menumeta.MenuItemFactory(
-        menu.BrowserMenuItem,
-        title=u'Object',
-        action=context.objectName + '/@@SelectedManagementView.html',
-        permission=CheckerPublic,
-        order=2,
-        _for=interfaces.IMountPoint)
-    return factory(context, request)

Deleted: z3c.mountpoint/trunk/browser.zcml
===================================================================
--- z3c.mountpoint/trunk/browser.zcml	2010-07-29 06:50:08 UTC (rev 115189)
+++ z3c.mountpoint/trunk/browser.zcml	2010-07-29 06:52:35 UTC (rev 115190)
@@ -1,40 +0,0 @@
-<configure
-    xmlns="http://namespaces.zope.org/browser"
-    xmlns:zope="http://namespaces.zope.org/zope">
-
-  <addform
-      name="addMounPoint.html"
-      schema=".interfaces.IMountPoint"
-      label="Add a Mount Point"
-      content_factory=".mountpoint.MountPoint"
-      fields="connectionName objectPath objectName"
-      set_before_add="connectionName objectPath objectName"
-      permission="zope.ManageContent"
-      />
-
-  <addMenuItem
-      class=".mountpoint.MountPoint"
-      title="Mount Point"
-      description="A Mount Point"
-      permission="zope.ManageContent"
-      view="addMounPoint.html"
-      />
-
-  <editform
-      name="edit.html"
-      schema=".interfaces.IMountPoint"
-      label="Edit Mount Point"
-      fields="connectionName objectPath objectName"
-      permission="zope.ManageContent"
-      menu="zmi_views" title="Edit"
-      />
-
-  <zope:adapter
-      factory=".browser.ObjectMenuItem"
-      for=".interfaces.IMountPoint
-           zope.publisher.interfaces.browser.IDefaultBrowserLayer"
-      provides="zope.app.menus.zmi_views"
-      name="Object"
-      />
-
-</configure>

Copied: z3c.mountpoint/trunk/buildout.cfg (from rev 100517, z3c.pagelet/trunk/buildout.cfg)
===================================================================
--- z3c.mountpoint/trunk/buildout.cfg	                        (rev 0)
+++ z3c.mountpoint/trunk/buildout.cfg	2010-07-29 06:52:35 UTC (rev 115190)
@@ -0,0 +1,7 @@
+[buildout]
+develop = .
+parts = test
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = z3c.mountpoint [test]

Deleted: z3c.mountpoint/trunk/configure.zcml
===================================================================
--- z3c.mountpoint/trunk/configure.zcml	2010-07-29 06:50:08 UTC (rev 115189)
+++ z3c.mountpoint/trunk/configure.zcml	2010-07-29 06:52:35 UTC (rev 115190)
@@ -1,39 +0,0 @@
-<configure
-    xmlns="http://namespaces.zope.org/zope"
-    xmlns:browser="http://namespaces.zope.org/browser"
-    i18n_domain='zope'
-    >
-
-  <utility
-      component=".connection.ZODBConnectionNamesVocabulary"
-      provides="zope.schema.interfaces.IVocabularyFactory"
-      name="ZODB Connection Names"
-      />
-
-  <class class=".mountpoint.MountPoint">
-    <implements
-        interface="zope.annotation.interfaces.IAttributeAnnotatable"
-        />
-    <require
-        permission="zope.View"
-        interface=".interfaces.IMountPoint"
-        />
-    <require
-        permission="zope.ManageContent"
-        set_schema=".interfaces.IMountPoint"
-        />
-  </class>
-
-  <adapter
-      factory=".mountpoint.MountPointTraverser"
-      />
-
-  <adapter
-      factory=".remoteproxy.RemoteLocationProxyTraverser"
-      />
-
-  <subscriber handler=".mountpoint.updateMountedObject" />
-
-  <include file="browser.zcml" />
-
-</configure>

Deleted: z3c.mountpoint/trunk/connection.py
===================================================================
--- z3c.mountpoint/trunk/connection.py	2010-07-29 06:50:08 UTC (rev 115189)
+++ z3c.mountpoint/trunk/connection.py	2010-07-29 06:52:35 UTC (rev 115190)
@@ -1,25 +0,0 @@
-##############################################################################
-#
-# 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.
-#
-##############################################################################
-"""A simple multi-database mount-point implementation
-
-$Id$
-"""
-__docformat__ = "reStructuredText"
-from zope.schema import vocabulary
-from zope.app.component import hooks
-
-def ZODBConnectionNamesVocabulary(context):
-    return vocabulary.SimpleVocabulary(
-        [vocabulary.SimpleTerm(name)
-         for name in hooks.getSite()._p_jar.db().databases])

Deleted: z3c.mountpoint/trunk/interfaces.py
===================================================================
--- z3c.mountpoint/trunk/interfaces.py	2010-07-29 06:50:08 UTC (rev 115189)
+++ z3c.mountpoint/trunk/interfaces.py	2010-07-29 06:52:35 UTC (rev 115190)
@@ -1,57 +0,0 @@
-##############################################################################
-#
-# 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.
-#
-##############################################################################
-"""A simple multi-database mount-point implementation
-
-$Id$
-"""
-__docformat__ = "reStructuredText"
-import zope.interface
-import zope.schema
-
-
-class IMountPoint(zope.interface.Interface):
-    """A simple mount point."""
-
-    connectionName = zope.schema.Choice(
-        title=u'Conenction Name',
-        vocabulary='ZODB Connection Names',
-        required=True)
-
-    objectPath = zope.schema.TextLine(
-        title=u'Object Path',
-        default=u'/',
-        required=True)
-
-    objectName = zope.schema.TextLine(
-        title=u'Object Name',
-        description=u'The name under which the object will be known '
-                    u'when traversing from the mount point.',
-        default=u'object',
-        required=True)
-
-    object = zope.schema.Field(
-        title=u'Foreign object')
-
-    def update():
-        """Update the mounted object."""
-
-
-class IRemoteLocationProxy(zope.interface.Interface):
-    """Remote Location Proxy
-
-    When an object from a different object database is used, the directly
-    specified parent is not the correct one anymore. The parent should point
-    to the local mount point and subsequent objects in the path to the
-    location proxied parent.
-    """

Deleted: z3c.mountpoint/trunk/mountpoint.py
===================================================================
--- z3c.mountpoint/trunk/mountpoint.py	2010-07-29 06:50:08 UTC (rev 115189)
+++ z3c.mountpoint/trunk/mountpoint.py	2010-07-29 06:52:35 UTC (rev 115190)
@@ -1,82 +0,0 @@
-##############################################################################
-#
-# 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.
-#
-##############################################################################
-"""A simple multi-database mount-point implementation
-
-$Id$
-"""
-__docformat__ = "reStructuredText"
-import persistent
-import zope.component
-import zope.interface
-import zope.lifecycleevent
-import zope.location
-from zope.app.container import contained
-from zope.app.publication import traversers
-from zope.publisher.interfaces.browser import IBrowserRequest, IBrowserPublisher
-from zope.security.proxy import removeSecurityProxy
-from zope.traversing import api
-
-from z3c.mountpoint import interfaces, remoteproxy
-
-class MountPoint(persistent.Persistent, contained.Contained):
-    """A simple mount point."""
-    zope.interface.implements(interfaces.IMountPoint)
-
-    def __init__(self, connectionName=None, objectPath=u'/', objectName=u'object'):
-        self.connectionName = connectionName
-        self.objectPath = objectPath
-        self.objectName = objectName
-        self.object = None
-
-    def update(self):
-        parent = self.__parent__
-        if parent is not None:
-            # Get the connection by name
-            conn = parent._p_jar.get_connection(self.connectionName)
-            obj = conn.root()['Application']
-            obj = api.traverse(obj, self.objectPath)
-            self.object = obj
-        else:
-            self.object = None
-
-    @apply
-    def __parent__():
-        def get(self):
-            return self and self.__dict__.get('__parent__', None)
-        def set(self, parent):
-            self.__dict__['__parent__'] = parent
-            self.update()
-        return property(get, set)
-
-
-class MountPointTraverser(traversers.SimpleComponentTraverser):
-
-    zope.component.adapts(interfaces.IMountPoint, IBrowserRequest)
-    zope.interface.implementsOnly(IBrowserPublisher)
-
-    def publishTraverse(self, request, name):
-        if name == self.context.objectName:
-            # Remove the security proxy, because we need a bare object to wrap
-            # the location proxy around.
-            context = removeSecurityProxy(self.context)
-            return remoteproxy.RemoteLocationProxy(
-                context.object, context, self.context.objectName)
-        return super(MountPointTraverser, self).publishTraverse(
-            request, name)
-
-
- at zope.component.adapter(
-    interfaces.IMountPoint, zope.lifecycleevent.IObjectModifiedEvent)
-def updateMountedObject(mountPoint, event):
-    mountPoint.update()

Deleted: z3c.mountpoint/trunk/remoteproxy.py
===================================================================
--- z3c.mountpoint/trunk/remoteproxy.py	2010-07-29 06:50:08 UTC (rev 115189)
+++ z3c.mountpoint/trunk/remoteproxy.py	2010-07-29 06:52:35 UTC (rev 115190)
@@ -1,70 +0,0 @@
-##############################################################################
-#
-# 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.
-#
-##############################################################################
-"""Remote object traverser.
-
-$Id$
-"""
-__docformat__ = "reStructuredText"
-import zope.interface
-from zope.interface import declarations
-from zope.proxy import getProxiedObject, removeAllProxies
-from zope.proxy.decorator import DecoratorSpecificationDescriptor
-from zope.publisher.interfaces.browser import IBrowserPublisher, IBrowserRequest
-
-from z3c.mountpoint import interfaces
-
-class RemoteLocationProxyDecoratorSpecificationDescriptor(
-    DecoratorSpecificationDescriptor):
-
-    def __get__(self, inst, cls=None):
-        if inst is None:
-            return declarations.getObjectSpecification(cls)
-        else:
-            provided = zope.interface.providedBy(getProxiedObject(inst))
-
-            # Use type rather than __class__ because inst is a proxy and
-            # will return the proxied object's class.
-            cls = type(inst)
-            # Create a special version of Provides, which forces the remote
-            # location proxy to the front, so that a special traverser can be
-            # enforced.
-            return declarations.Provides(
-                cls, interfaces.IRemoteLocationProxy, provided)
-
-
-class RemoteLocationProxy(zope.location.LocationProxy):
-    """A location proxy for remote objects."""
-    __providedBy__ = RemoteLocationProxyDecoratorSpecificationDescriptor()
-
-
-class RemoteLocationProxyTraverser(object):
-    zope.component.adapts(interfaces.IRemoteLocationProxy, IBrowserRequest)
-    zope.interface.implements(IBrowserPublisher)
-
-    def __init__(self, context, request):
-        self.context = context
-        self.request = request
-
-    def browserDefault(self, request):
-        ob = self.context
-        view_name = zapi.getDefaultViewName(ob, request)
-        return ob, (view_name,)
-
-    def publishTraverse(self, request, name):
-        pureContext = removeAllProxies(self.context)
-        traverser = zope.component.getMultiAdapter(
-            (pureContext, self.request), IBrowserPublisher)
-        result = traverser.publishTraverse(request, name)
-        # Only remove the security proxy from the context.
-        return RemoteLocationProxy(result, getProxiedObject(self.context), name)

Copied: z3c.mountpoint/trunk/setup.py (from rev 100519, z3c.pagelet/trunk/setup.py)
===================================================================
--- z3c.mountpoint/trunk/setup.py	                        (rev 0)
+++ z3c.mountpoint/trunk/setup.py	2010-07-29 06:52:35 UTC (rev 115190)
@@ -0,0 +1,85 @@
+##############################################################################
+#
+# Copyright (c) 2007-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.
+#
+##############################################################################
+"""Setup
+
+$Id$
+"""
+import os
+from setuptools import setup, find_packages
+
+def read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+version = '0.1dev'
+
+setup(
+    name='z3c.mountpoint',
+    version=version,
+    author = "Stephan Richter and the Zope Community",
+    author_email = "zope-dev at zope.org",
+    description = (
+        "Very simple implementation of a mount point for an object in "
+        "another ZODB connection."),
+    long_description=(
+        read('src', 'z3c', 'mountpoint', 'README.txt')
+        + '\n\n' +
+        read('CHANGES.txt')
+        ),
+    license = "ZPL 2.1",
+    keywords = "zope3 zodb mount mountpoint",
+    classifiers = [
+        'Development Status :: 3 - Alpha',
+        'Environment :: Web Environment',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: Zope Public License',
+        'Programming Language :: Python',
+        'Natural Language :: English',
+        'Operating System :: OS Independent',
+        'Topic :: Internet :: WWW/HTTP',
+        'Framework :: Zope3'],
+    url = 'http://pypi.python.org/pypi/z3c.mountpoint',
+    packages = find_packages('src'),
+    package_dir = {'':'src'},
+    namespace_packages = ['z3c'],
+    extras_require = dict(
+        test = [
+            'zope.app.testing',
+            'zope.app.publication',
+                # 'zope.testing',
+                # 'zope.traversing',
+                # 'lxml>=2.1.1',
+                # 'z3c.pt>=1.0b4',
+                # 'z3c.ptcompat',
+                # 'zope.app.security',
+                # 'zope.formlib',
+                ],
+        ),
+    install_requires = [
+        'setuptools',
+        # 'z3c.template>=1.2.0',
+        # 'z3c.ptcompat',
+        #  # TODO: this is only needed for ZCML directives, so can copy
+        # 'zope.app.publisher', # things we use from there and get rid of the dependencies.
+        'zope.component',
+        'zope.app.container',
+        # 'zope.configuration',
+        # 'zope.contentprovider',
+        # 'zope.interface',
+        # 'zope.publisher',
+        # 'zope.schema',
+        # 'zope.security',
+        ],
+    include_package_data = True,
+    zip_safe = False,
+    )

Copied: z3c.mountpoint/trunk/src/z3c/mountpoint/README.txt (from rev 115115, z3c.mountpoint/trunk/README.txt)
===================================================================
--- z3c.mountpoint/trunk/src/z3c/mountpoint/README.txt	                        (rev 0)
+++ z3c.mountpoint/trunk/src/z3c/mountpoint/README.txt	2010-07-29 06:52:35 UTC (rev 115190)
@@ -0,0 +1,122 @@
+================
+ZODB Mount Point
+================
+
+This package provides a very simple implementation of a mount point for an
+object in another ZODB connection. If you have multiple connections defined in
+your ``zope.conf`` configuration file or multiple databases defined in your
+Python code, you can use this package to mount any object from any database at
+any location of another database.
+
+Let's start by creating two databases in the typical Zope 3 application layout:
+
+  >>> from ZODB.tests.test_storage import MinimalMemoryStorage
+  >>> from ZODB import DB
+  >>> from zope.site.folder import rootFolder, Folder
+  >>> import transaction
+
+  >>> dbmap = {}
+
+  >>> db1 = DB(MinimalMemoryStorage(), database_name='db1', databases=dbmap)
+  >>> conn1 = db1.open()
+  >>> conn1.root()['Application'] = rootFolder()
+
+  >>> db2 = DB(MinimalMemoryStorage(), database_name='db2', databases=dbmap)
+  >>> conn2 = db2.open()
+  >>> conn2.root()['Application'] = rootFolder()
+
+  >>> transaction.commit()
+
+Let's now add a sub-folder to the second database, which will serve as the
+object which we wish to mount:
+
+  >>> conn2.root()['Application']['Folder2-1'] = Folder()
+  >>> transaction.commit()
+
+We can now create a mount point:
+
+  >>> from z3c.mountpoint import mountpoint
+  >>> mountPoint = mountpoint.MountPoint(
+  ...     'db2', objectPath=u'/Folder2-1', objectName=u'F2-1')
+
+The first argument to the constructor is the connection name of the database,
+the second argument is the path to the mounted object within the mounted DB
+and the object name is the name under which the object is mounted.
+
+Now we can add the mount point to the first database:
+
+  >>> conn1.root()['Application']['mp'] = mountPoint
+  >>> transaction.commit()
+
+We can now access the mounted object as follows:
+
+  >>> conn1.root()['Application']['mp'].object
+  <zope.site.folder.Folder object at ...>
+
+Note that the object name is not yet used; it is for traversal only.
+
+
+Traversal
+---------
+
+So let's have a look at the traversal next. Before being able to traverse, we
+need to register the special mount point traverser:
+
+  >>> import zope.component
+  >>> zope.component.provideAdapter(mountpoint.MountPointTraverser)
+
+We should now be able to traverse to the mounted object now:
+
+  >>> from zope.publisher.browser import TestRequest
+  >>> req = TestRequest()
+
+  >>> from zope.traversing.publicationtraverse import PublicationTraverser
+  >>> traverser = PublicationTraverser()
+  >>> traverser.traversePath(req, conn1.root()['Application'], 'mp/F2-1')
+  <zope.site.folder.Folder object at ...>
+
+When we add a new object remotely, it available via the mount point as well:
+
+  >>> conn2.root()['Application']['Folder2-1']['Folder2-1.1'] = Folder()
+  >>> transaction.commit()
+
+  >>> tuple(traverser.traversePath(
+  ...    req, conn1.root()['Application'], 'mp/F2-1').keys())
+  (u'Folder2-1.1',)
+
+Now, by default the objects refer to their original path:
+
+  >>> f211 = traverser.traversePath(
+  ...    req, conn1.root()['Application'], 'mp/F2-1/Folder2-1.1')
+
+  >>> from zope.traversing.browser import absoluteurl
+  >>> absoluteurl.absoluteURL(f211, req)
+  'http://127.0.0.1/Folder2-1/Folder2-1.1'
+
+This package solves that problem by wrapping all object by a special remote
+location proxy and providing a special wrapping traverser for those proxies:
+
+  >>> from z3c.mountpoint import remoteproxy
+  >>> zope.component.provideAdapter(remoteproxy.RemoteLocationProxyTraverser)
+
+  >>> f211 = traverser.traversePath(
+  ...    req, conn1.root()['Application'], 'mp/F2-1/Folder2-1.1')
+  >>> absoluteurl.absoluteURL(f211, req)
+  'http://127.0.0.1/mp/F2-1/Folder2-1.1'
+
+
+Updating the Mount Point
+------------------------
+
+Whenever any attribute on the mount point is modified, the mount object is
+updated. For example, when the object path is changed, the object is adjusted
+as well. This is done with an event subscriber:
+
+  >>> mountPoint.objectPath = u'/Folder2-1/Folder2-1.1'
+
+  >>> modifiedEvent = object()
+  >>> mountpoint.updateMountedObject(mountPoint, modifiedEvent)
+
+  >>> f211 == mountPoint.object
+  True
+

Copied: z3c.mountpoint/trunk/src/z3c/mountpoint/__init__.py (from rev 115115, z3c.mountpoint/trunk/__init__.py)
===================================================================
--- z3c.mountpoint/trunk/src/z3c/mountpoint/__init__.py	                        (rev 0)
+++ z3c.mountpoint/trunk/src/z3c/mountpoint/__init__.py	2010-07-29 06:52:35 UTC (rev 115190)
@@ -0,0 +1 @@
+# Make a package.

Copied: z3c.mountpoint/trunk/src/z3c/mountpoint/browser.py (from rev 115115, z3c.mountpoint/trunk/browser.py)
===================================================================
--- z3c.mountpoint/trunk/src/z3c/mountpoint/browser.py	                        (rev 0)
+++ z3c.mountpoint/trunk/src/z3c/mountpoint/browser.py	2010-07-29 06:52:35 UTC (rev 115190)
@@ -0,0 +1,32 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Browser code
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+from zope.app.publisher.browser import menu, menumeta
+from zope.security.checker import CheckerPublic
+
+from z3c.mountpoint import interfaces
+
+def ObjectMenuItem(context, request):
+    factory = menumeta.MenuItemFactory(
+        menu.BrowserMenuItem,
+        title=u'Object',
+        action=context.objectName + '/@@SelectedManagementView.html',
+        permission=CheckerPublic,
+        order=2,
+        _for=interfaces.IMountPoint)
+    return factory(context, request)

Copied: z3c.mountpoint/trunk/src/z3c/mountpoint/browser.zcml (from rev 115115, z3c.mountpoint/trunk/browser.zcml)
===================================================================
--- z3c.mountpoint/trunk/src/z3c/mountpoint/browser.zcml	                        (rev 0)
+++ z3c.mountpoint/trunk/src/z3c/mountpoint/browser.zcml	2010-07-29 06:52:35 UTC (rev 115190)
@@ -0,0 +1,40 @@
+<configure
+    xmlns="http://namespaces.zope.org/browser"
+    xmlns:zope="http://namespaces.zope.org/zope">
+
+  <addform
+      name="addMounPoint.html"
+      schema=".interfaces.IMountPoint"
+      label="Add a Mount Point"
+      content_factory=".mountpoint.MountPoint"
+      fields="connectionName objectPath objectName"
+      set_before_add="connectionName objectPath objectName"
+      permission="zope.ManageContent"
+      />
+
+  <addMenuItem
+      class=".mountpoint.MountPoint"
+      title="Mount Point"
+      description="A Mount Point"
+      permission="zope.ManageContent"
+      view="addMounPoint.html"
+      />
+
+  <editform
+      name="edit.html"
+      schema=".interfaces.IMountPoint"
+      label="Edit Mount Point"
+      fields="connectionName objectPath objectName"
+      permission="zope.ManageContent"
+      menu="zmi_views" title="Edit"
+      />
+
+  <zope:adapter
+      factory=".browser.ObjectMenuItem"
+      for=".interfaces.IMountPoint
+           zope.publisher.interfaces.browser.IDefaultBrowserLayer"
+      provides="zope.app.menus.zmi_views"
+      name="Object"
+      />
+
+</configure>

Copied: z3c.mountpoint/trunk/src/z3c/mountpoint/configure.zcml (from rev 115115, z3c.mountpoint/trunk/configure.zcml)
===================================================================
--- z3c.mountpoint/trunk/src/z3c/mountpoint/configure.zcml	                        (rev 0)
+++ z3c.mountpoint/trunk/src/z3c/mountpoint/configure.zcml	2010-07-29 06:52:35 UTC (rev 115190)
@@ -0,0 +1,39 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain='zope'
+    >
+
+  <utility
+      component=".connection.ZODBConnectionNamesVocabulary"
+      provides="zope.schema.interfaces.IVocabularyFactory"
+      name="ZODB Connection Names"
+      />
+
+  <class class=".mountpoint.MountPoint">
+    <implements
+        interface="zope.annotation.interfaces.IAttributeAnnotatable"
+        />
+    <require
+        permission="zope.View"
+        interface=".interfaces.IMountPoint"
+        />
+    <require
+        permission="zope.ManageContent"
+        set_schema=".interfaces.IMountPoint"
+        />
+  </class>
+
+  <adapter
+      factory=".mountpoint.MountPointTraverser"
+      />
+
+  <adapter
+      factory=".remoteproxy.RemoteLocationProxyTraverser"
+      />
+
+  <subscriber handler=".mountpoint.updateMountedObject" />
+
+  <include file="browser.zcml" />
+
+</configure>

Copied: z3c.mountpoint/trunk/src/z3c/mountpoint/connection.py (from rev 115115, z3c.mountpoint/trunk/connection.py)
===================================================================
--- z3c.mountpoint/trunk/src/z3c/mountpoint/connection.py	                        (rev 0)
+++ z3c.mountpoint/trunk/src/z3c/mountpoint/connection.py	2010-07-29 06:52:35 UTC (rev 115190)
@@ -0,0 +1,25 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""A simple multi-database mount-point implementation
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+from zope.schema import vocabulary
+from zope.app.component import hooks
+
+def ZODBConnectionNamesVocabulary(context):
+    return vocabulary.SimpleVocabulary(
+        [vocabulary.SimpleTerm(name)
+         for name in hooks.getSite()._p_jar.db().databases])

Copied: z3c.mountpoint/trunk/src/z3c/mountpoint/interfaces.py (from rev 115115, z3c.mountpoint/trunk/interfaces.py)
===================================================================
--- z3c.mountpoint/trunk/src/z3c/mountpoint/interfaces.py	                        (rev 0)
+++ z3c.mountpoint/trunk/src/z3c/mountpoint/interfaces.py	2010-07-29 06:52:35 UTC (rev 115190)
@@ -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.
+#
+##############################################################################
+"""A simple multi-database mount-point implementation
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+import zope.interface
+import zope.schema
+
+
+class IMountPoint(zope.interface.Interface):
+    """A simple mount point."""
+
+    connectionName = zope.schema.Choice(
+        title=u'Conenction Name',
+        vocabulary='ZODB Connection Names',
+        required=True)
+
+    objectPath = zope.schema.TextLine(
+        title=u'Object Path',
+        default=u'/',
+        required=True)
+
+    objectName = zope.schema.TextLine(
+        title=u'Object Name',
+        description=u'The name under which the object will be known '
+                    u'when traversing from the mount point.',
+        default=u'object',
+        required=True)
+
+    object = zope.schema.Field(
+        title=u'Foreign object')
+
+    def update():
+        """Update the mounted object."""
+
+
+class IRemoteLocationProxy(zope.interface.Interface):
+    """Remote Location Proxy
+
+    When an object from a different object database is used, the directly
+    specified parent is not the correct one anymore. The parent should point
+    to the local mount point and subsequent objects in the path to the
+    location proxied parent.
+    """

Copied: z3c.mountpoint/trunk/src/z3c/mountpoint/mountpoint.py (from rev 115115, z3c.mountpoint/trunk/mountpoint.py)
===================================================================
--- z3c.mountpoint/trunk/src/z3c/mountpoint/mountpoint.py	                        (rev 0)
+++ z3c.mountpoint/trunk/src/z3c/mountpoint/mountpoint.py	2010-07-29 06:52:35 UTC (rev 115190)
@@ -0,0 +1,82 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""A simple multi-database mount-point implementation
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+import persistent
+import zope.component
+import zope.interface
+import zope.lifecycleevent
+import zope.location
+from zope.app.container import contained
+from zope.app.publication import traversers
+from zope.publisher.interfaces.browser import IBrowserRequest, IBrowserPublisher
+from zope.security.proxy import removeSecurityProxy
+from zope.traversing import api
+
+from z3c.mountpoint import interfaces, remoteproxy
+
+class MountPoint(persistent.Persistent, contained.Contained):
+    """A simple mount point."""
+    zope.interface.implements(interfaces.IMountPoint)
+
+    def __init__(self, connectionName=None, objectPath=u'/', objectName=u'object'):
+        self.connectionName = connectionName
+        self.objectPath = objectPath
+        self.objectName = objectName
+        self.object = None
+
+    def update(self):
+        parent = self.__parent__
+        if parent is not None:
+            # Get the connection by name
+            conn = parent._p_jar.get_connection(self.connectionName)
+            obj = conn.root()['Application']
+            obj = api.traverse(obj, self.objectPath)
+            self.object = obj
+        else:
+            self.object = None
+
+    @apply
+    def __parent__():
+        def get(self):
+            return self and self.__dict__.get('__parent__', None)
+        def set(self, parent):
+            self.__dict__['__parent__'] = parent
+            self.update()
+        return property(get, set)
+
+
+class MountPointTraverser(traversers.SimpleComponentTraverser):
+
+    zope.component.adapts(interfaces.IMountPoint, IBrowserRequest)
+    zope.interface.implementsOnly(IBrowserPublisher)
+
+    def publishTraverse(self, request, name):
+        if name == self.context.objectName:
+            # Remove the security proxy, because we need a bare object to wrap
+            # the location proxy around.
+            context = removeSecurityProxy(self.context)
+            return remoteproxy.RemoteLocationProxy(
+                context.object, context, self.context.objectName)
+        return super(MountPointTraverser, self).publishTraverse(
+            request, name)
+
+
+ at zope.component.adapter(
+    interfaces.IMountPoint, zope.lifecycleevent.IObjectModifiedEvent)
+def updateMountedObject(mountPoint, event):
+    mountPoint.update()

Copied: z3c.mountpoint/trunk/src/z3c/mountpoint/remoteproxy.py (from rev 115115, z3c.mountpoint/trunk/remoteproxy.py)
===================================================================
--- z3c.mountpoint/trunk/src/z3c/mountpoint/remoteproxy.py	                        (rev 0)
+++ z3c.mountpoint/trunk/src/z3c/mountpoint/remoteproxy.py	2010-07-29 06:52:35 UTC (rev 115190)
@@ -0,0 +1,70 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Remote object traverser.
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+import zope.interface
+from zope.interface import declarations
+from zope.proxy import getProxiedObject, removeAllProxies
+from zope.proxy.decorator import DecoratorSpecificationDescriptor
+from zope.publisher.interfaces.browser import IBrowserPublisher, IBrowserRequest
+
+from z3c.mountpoint import interfaces
+
+class RemoteLocationProxyDecoratorSpecificationDescriptor(
+    DecoratorSpecificationDescriptor):
+
+    def __get__(self, inst, cls=None):
+        if inst is None:
+            return declarations.getObjectSpecification(cls)
+        else:
+            provided = zope.interface.providedBy(getProxiedObject(inst))
+
+            # Use type rather than __class__ because inst is a proxy and
+            # will return the proxied object's class.
+            cls = type(inst)
+            # Create a special version of Provides, which forces the remote
+            # location proxy to the front, so that a special traverser can be
+            # enforced.
+            return declarations.Provides(
+                cls, interfaces.IRemoteLocationProxy, provided)
+
+
+class RemoteLocationProxy(zope.location.LocationProxy):
+    """A location proxy for remote objects."""
+    __providedBy__ = RemoteLocationProxyDecoratorSpecificationDescriptor()
+
+
+class RemoteLocationProxyTraverser(object):
+    zope.component.adapts(interfaces.IRemoteLocationProxy, IBrowserRequest)
+    zope.interface.implements(IBrowserPublisher)
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+    def browserDefault(self, request):
+        ob = self.context
+        view_name = zapi.getDefaultViewName(ob, request)
+        return ob, (view_name,)
+
+    def publishTraverse(self, request, name):
+        pureContext = removeAllProxies(self.context)
+        traverser = zope.component.getMultiAdapter(
+            (pureContext, self.request), IBrowserPublisher)
+        result = traverser.publishTraverse(request, name)
+        # Only remove the security proxy from the context.
+        return RemoteLocationProxy(result, getProxiedObject(self.context), name)

Copied: z3c.mountpoint/trunk/src/z3c/mountpoint/tests.py (from rev 115115, z3c.mountpoint/trunk/tests.py)
===================================================================
--- z3c.mountpoint/trunk/src/z3c/mountpoint/tests.py	                        (rev 0)
+++ z3c.mountpoint/trunk/src/z3c/mountpoint/tests.py	2010-07-29 06:52:35 UTC (rev 115190)
@@ -0,0 +1,53 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Browser code
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+from zope.app.publication import traversers
+from zope.app.testing import placelesssetup, setup
+from zope.publisher.interfaces.browser import IBrowserPublisher, IBrowserRequest
+from zope.security import checker
+from zope.site import folder
+from zope.site.interfaces import IFolder
+from zope.traversing.testing import setUp as traversalSetUp
+import doctest
+import unittest
+import zope.component
+import zope.interface
+
+from z3c.mountpoint import interfaces, mountpoint
+
+def setUp(test):
+    placelesssetup.setUp(test)
+    traversalSetUp()
+    # The test traverser is all we need.
+    zope.component.provideAdapter(
+        traversers.TestTraverser,
+        (zope.interface.Interface, IBrowserRequest), IBrowserPublisher)
+    # A simple interface checker for: MountPoint
+    checker.defineChecker(
+        mountpoint.MountPoint, checker.InterfaceChecker(interfaces.IMountPoint))
+    # A simple interface checker for: Folder
+    checker.defineChecker(
+        folder.Folder, checker.InterfaceChecker(IFolder))
+
+def test_suite():
+    return unittest.TestSuite((
+        doctest.DocFileSuite('README.txt',
+                     setUp=setUp, tearDown=placelesssetup.tearDown,
+                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                     ),
+        ))

Deleted: z3c.mountpoint/trunk/tests.py
===================================================================
--- z3c.mountpoint/trunk/tests.py	2010-07-29 06:50:08 UTC (rev 115189)
+++ z3c.mountpoint/trunk/tests.py	2010-07-29 06:52:35 UTC (rev 115190)
@@ -1,53 +0,0 @@
-##############################################################################
-#
-# 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.
-#
-##############################################################################
-"""Browser code
-
-$Id$
-"""
-__docformat__ = "reStructuredText"
-import unittest
-import zope.component
-import zope.interface
-from zope.app.folder import folder
-from zope.app.folder.interfaces import IFolder
-from zope.app.publication import traversers
-from zope.app.testing import placelesssetup, setup
-from zope.publisher.interfaces.browser import IBrowserPublisher, IBrowserRequest
-from zope.security import checker
-from zope.testing import doctest
-from zope.traversing.testing import setUp as traversalSetUp
-
-from z3c.mountpoint import interfaces, mountpoint
-
-def setUp(test):
-    placelesssetup.setUp(test)
-    traversalSetUp()
-    # The test traverser is all we need.
-    zope.component.provideAdapter(
-        traversers.TestTraverser,
-        (zope.interface.Interface, IBrowserRequest), IBrowserPublisher)
-    # A simple interface checker for: MountPoint
-    checker.defineChecker(
-        mountpoint.MountPoint, checker.InterfaceChecker(interfaces.IMountPoint))
-    # A simple interface checker for: Folder
-    checker.defineChecker(
-        folder.Folder, checker.InterfaceChecker(IFolder))
-
-def test_suite():
-    return unittest.TestSuite((
-        doctest.DocFileSuite('README.txt',
-                     setUp=setUp, tearDown=placelesssetup.tearDown,
-                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
-                     ),
-        ))



More information about the checkins mailing list