[Zope3-checkins] CVS: Zope3/src/zope/app/component - hooks.py:1.5.8.11

Steve Alexander steve@cat-box.net
Fri, 16 May 2003 12:19:09 -0400


Update of /cvs-repository/Zope3/src/zope/app/component
In directory cvs.zope.org:/tmp/cvs-serv2621/src/zope/app/component

Modified Files:
      Tag: stevea-decorators-branch
	hooks.py 
Log Message:
All unit tests now pass.
Added an ensureContextWrapped function to zope.proxy.context.

In code that uses context wrapping, we have two situations:

  * Code such as traversal code wants to ensure that there is a context-
    wrapper, and set the parent and items in the context dict.
    If there is no context wrapper, it should create one, but if there
    is one already, it should be preserved.

  * Code that is the primary source of some information, and wants to
    wrap it and add minimal information (name, usually) before allowing
    the world to see the information. The zopecontainerdecorator is an
    example of this.

To resolve these situations, the former code should use
ensureContextWrapped, which keeps an existing context wrapper if possible,
and updates the context and adds/overwrites items in the context dict.
The latter code can continue to use ContextWrapper.



=== Zope3/src/zope/app/component/hooks.py 1.5.8.10 => 1.5.8.11 ===
--- Zope3/src/zope/app/component/hooks.py:1.5.8.10	Fri May 16 09:52:17 2003
+++ Zope3/src/zope/app/component/hooks.py	Fri May 16 12:18:38 2003
@@ -65,6 +65,29 @@
 
     return serviceManager
 
+# There are several semantically different ContextWrapper calls:
+#
+# 1: Used by application code:
+#    here is an object, with its parent and its name
+#
+# 2: Used by traversal system:
+#    here is an object, the parent it came from, and its name (and other stuff)
+#
+# 3: Used by the namespaces traversal:
+#    add extra context to something already traversed
+
+# The traversal system should say:
+#
+#   container, please give me an object
+#   if the object is wrapped, assume the wrapper is of the appropriate type,
+#       and alter its dict and parent if not.
+#   otherwise, wrap the object
+#
+# The namespaces traversal should say:
+#
+#   Add *context* to what we already have.
+#   So, it should explicitly use a Context *Wrapper* not a decorator.
+
 def ContextWrapper_hook(_ob, _parent, **kw):
     """Decoration-aware replacement for zope.proxy.context.ContextWrapper_hook
     """
@@ -98,6 +121,14 @@
     The wrapped object will declare that it provides the interfaces that the
     wrapped object provides plus the interfaces given in the DecoratorSpec.
     """
+    if type(ob) is Decorator:
+        # XXX If we choose to have other kinds of decorators in the future
+        #     then, we'll need to add 'decorator':'context' into the wrapper
+        #     dict, and refuse to context-wrap when there's already a
+        #     decorator in the wrapper chain.
+        #
+        #     For now, just check that the object isn't a decorator.
+        raise TypeError("Tried to decorate a Decorator instance.")
     obj_is_proxy = type(ob) is Proxy
     if obj_is_proxy:
         checker = getChecker(ob)