[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/ZopePublication - PublicationTraverse.py:1.1.2.18 Traversers.py:1.1.2.18 zopepublication.zcml:1.1.2.5
Jim Fulton
jim@zope.com
Thu, 23 May 2002 14:01:50 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/App/ZopePublication
In directory cvs.zope.org:/tmp/cvs-serv26429/lib/python/Zope/App/ZopePublication
Modified Files:
Tag: Zope-3x-branch
PublicationTraverse.py Traversers.py zopepublication.zcml
Log Message:
This all started with wanting to be able to use url;view in a ZPT path. :)
That lead me to:
- Massive traversal refactoring.
Namespace handling is now centralized in Zope.App.Traversing.
- ZPT refactoring, including some renaming that touches pretty much everything. :)
- The application specific ZPT support was moved into
Zope.App.PageTemplate.
- To get page template files (for use in views):
from Zope.App.PageTemplate import ViewPageTemplateFile
- Fixed up security so that ZPT expressions only have access to
safe builtins and so that modules namespace does imports safely.
- Got ZPTPage working!
- renaming url to absolute_url and got absolute_url to work in paths.
- Cleaned up the (as yet unused) RestrictedInterpreter module in
Zope.Security. In particular, changed to use a separate
RestrictedBuiltins module.
=== Zope3/lib/python/Zope/App/ZopePublication/PublicationTraverse.py 1.1.2.17 => 1.1.2.18 ===
import ApplicationController
from Zope.Proxy.ProxyIntrospection import removeAllProxies
-from Zope.ComponentArchitecture.Exceptions import ComponentLookupError
+from Zope.App.Traversing.Namespaces import namespaceLookup
+from Zope.App.Traversing.ParameterParsing import parameterizedNameParse
class DuplicateNamespaces(Exception):
"""More than one namespace was specified in a request"""
@@ -34,9 +35,6 @@
class UnknownNamespace(Exception):
"""A parameter specified an unknown namespace"""
-class ExcessiveWrapping(NotFound):
- """Too many levels of acquisition wrapping. We don't believe them."""
-
class PublicationTraverse:
def traverseName(self, request, ob, name):
@@ -44,48 +42,32 @@
nm = name # the name to look up the object with
if name.find(';') >= 0:
- # Process URI segment parameters. It makes sense to centralize
- # this here. Later it may be abstracted and distributed again,
- # but, if so it will be distributed to various path
- # traversers, rather than to traversal adapters/views.
- ns = ''
- parts = name.split(';')
- nm = parts[:1]
- for param in parts[1:]:
- l = param.find('=')
- if l >= 0:
- pname = param[:l]
- pval = param[l+1:]
- if pname == 'ns':
- if ns:
- raise DuplicateNamespaces(name)
- ns = pval
- else:
- pset = getattr(self, "_parameterSet%s" % pname,
- self # marker
- )
- if pset is self:
- # We don't know about this one, so leave it in the
- # name
- nm.append(param)
- else:
- pset(pname, pval, request)
+ # Process URI segment parameters.
+ ns, nm, parms = parameterizedNameParse(name)
+
+ unknown_parms = ()
+ for pname, pval in parms:
+ pset = getattr(self, "_parameterSet%s" % pname,
+ self # marker
+ )
+ if pset is self:
+ # We don't know about this one
+ unknown_parms += ((pname, pval),)
else:
- if ns:
- raise DuplicateNamespaces(name)
- ns = param
+ pset(pname, pval, request)
- nm = ';'.join(nm)
if ns:
- traverse = getattr(self, "_traverse%s" % ns,
- self # marker
- )
- if traverse is self:
- raise UnknownNamespace(ns, name)
-
- ob2 = traverse(request, ob, nm)
- return self._wrap(ob2, ob, name, nm)
- elif not nm:
+ ob2 = namespaceLookup(name, ns, nm, unknown_parms, ob, request)
+ return ContextWrapper(ob2, ob, name=name)
+
+ if unknown_parms:
+ nm = "%s;%s" % (
+ nm,
+ ';'.join(["%s=%s" % (parm[0], parm[1])
+ for parm in unknown_parms])
+ )
+
+ if not nm:
# Just set params, so skip
return ob
@@ -103,81 +85,7 @@
else:
raise NotFound(ob, name, request)
- return self._wrap(ob2, ob, name, nm)
-
- def _wrap(self, ob, parent, name, nm):
- wrapped = ContextWrapper(ob, parent, name=name)
- return wrapped
-
- def _traverseview(self, request, ob, name):
- # use self as marker
- r = getRequestView(ob, name, request, self)
- if r is self:
- raise NotFound(ob, name, request)
- return r
-
- def _traverseetc(self, request, ob, name):
- # XXX
-
- # This is here now to allow us to get service managers from a
- # separate namespace from the content. We add and etc
- # namespace to allow us to handle misc objects. We'll apply
- # YAGNI for now and hard code this. We'll want something more
- # general later. We were thinking of just calling "get"
- # methods, but this is probably too magic. In particular, we
- # will treat returned objects as sub-objects wrt security and
- # not all get methods may satisfy this assumption. It might be
- # best to introduce some sort of etc registry.
-
- if name == 'ApplicationController' and ob is None:
- return self.__etcApplicationController()
-
- if name != 'Services':
- raise NotFound(ob, name, request)
-
- try:
- return ob.getServiceManager()
- except AttributeError, ComponentLookupError:
- raise NotFound(ob, name, request)
-
- def __etcApplicationController(self):
- return ApplicationController
-
- def _traverseacquire(self, request, ob, name):
- """acquires content objects from higher in tree"""
- i = 0
- origOb=ob
- while i < 200:
- i = i + 1
- #r = getattr(ob, name, self) # no...
- # what we actually want to do is traverse ob, then parents, yes?
- # this is a cut and paste of the pertinent traverseName code;
- # clean to your pleasure, if desired.
- try:
- if request.getViewType().isImplementedBy(ob):
- ob2 = ob.publishTraverse(request, name)
- else:
- adapter = getRequestView(ob, '_traverse', request, self # marker
- )
-
- if adapter is not self:
- ob2 = adapter.publishTraverse(request, name)
- else:
- raise NotFound(ob, name, request)
- return ob2
-
- except NotFound:
- ob = getWrapperContext(ob)
- if ob is None:
- raise NotFound(origOb, name, request)
- raise ExcessiveWrapping(origOb, name, request)
-
- def _traversecreate(self, request, ob, name):
- for addable in getService(ob,'AddableContent').getAddables(ob):
- if addable.id == name:
- return addable
- raise NotFound(ob, name, request)
-
+ return ContextWrapper(ob2, ob, name=name)
class PublicationTraverser(PublicationTraverse):
=== Zope3/lib/python/Zope/App/ZopePublication/Traversers.py 1.1.2.17 => 1.1.2.18 ===
from Zope.ComponentArchitecture \
import getRequestView, getRequestDefaultViewName
+from Zope.ComponentArchitecture.Exceptions import ComponentLookupError
-class DefaultTraverser:
- """
+class SimpleComponentTraverser:
+ """Browser traverser for simple components that can only traverse to views
"""
__implements__ = IBrowserPublisher
@@ -25,27 +26,70 @@
self.target = target
def browserDefault(self, request):
- #XXX: (hack), we really need this to be component
- # specific.
ob = self.target
+
+ view_name = getRequestDefaultViewName(ob, request)
+
+ return ob, (view_name,)
+
+ def publishTraverse(self, request, name):
+ ob = self.target
+ try:
+ return getRequestView(ob, name, request)
+ except ComponentLookupError:
+ raise NotFound(ob, name)
+
- # if ob is not a component return
- if not hasattr(ob, '__implements__'):
- return ob,()
+
+class HTMLContentTraverser(SimpleComponentTraverser):
+ """Browser traverser for HTML content.
+
+ HTML content is content that authors expect to be used like simple
+ HTML pages. In particular, for the default view, URLs should be
+ relative to the container containing the content.
+ """
+
+ def browserDefault(self, request):
+ ob = self.target
view_name = getRequestDefaultViewName(ob, request)
+ view = self.publishTraverse(request, view_name)
+ if hasattr(view, 'browserDefault'):
+ view, path = view.browserDefault(request)
+ if len(path) == 1:
+ view = view.publishTraverse(request, path[0])
+ path = ()
+ else:
+ path = ()
+
+ return view, path
- view_uri = "%s;view" % view_name
- return ob, (view_uri,)
+class TestTraverser:
+ "Bobo-style traverser, mostly useful for testing"
+
+ __implements__ = IBrowserPublisher
+
+ def __init__(self, target):
+ self.target = target
+
+ def browserDefault(self, request):
+ ob = self.target
+
+ if hasattr(ob, '__implements__'):
+
+ view_name = getRequestDefaultViewName(ob, request)
+
+ return ob, (("%s;view" % view_name),)
+
+ return ob, ()
def publishTraverse(self, request, name):
- """ """
- # TODO: Look for default view
ob = self.target
- if name.startswith('_'):
- raise Unauthorized("Name %s begins with an underscore" % `name`)
if name.endswith(';view'):
return getRequestView( ob, name[:-5], request)
+
+ if name.startswith('_'):
+ raise Unauthorized("Name %s begins with an underscore" % `name`)
subob = getattr(ob, name, self) # self is marker here
if subob is self:
@@ -57,4 +101,3 @@
raise NotFound(ob, name, request)
return subob
-
=== Zope3/lib/python/Zope/App/ZopePublication/zopepublication.zcml 1.1.2.4 => 1.1.2.5 ===
<browser:view name="_traverse"
- factory="Zope.App.ZopePublication.Traversers.DefaultTraverser." />
+ for="Interface.Interface"
+ factory="Zope.App.ZopePublication.Traversers.SimpleComponentTraverser" />
+
+<browser:view name="_traverse"
+ for="Zope.App.OFS.Content.IHTMLContent."
+ factory="Zope.App.ZopePublication.Traversers.HTMLContentTraverser" />
<xmlrpc:view name="_traverse"
- factory=".Traversers.DefaultTraverser." />
+ for="Interface.Interface"
+ factory=".Traversers.SimpleComponentTraverser." />
<include package=".AbsoluteURL" file="config.zcml" />