[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/Traversing - AcquireNamespace.py:1.1.2.1 AttrItemNamespaces.py:1.1.2.1 CreateNamespace.py:1.1.2.1 EtcNamespace.py:1.1.2.1 Exceptions.py:1.1.2.1 INamespaceHandler.py:1.1.2.1 Namespaces.py:1.1.2.1 ParameterParsing.py:1.1.2.1 PresentationNamespaces.py:1.1.2.1 DefaultTraversable.py:1.1.2.6 ITraversable.py:1.1.2.3 Traverser.py:1.1.2.11
Jim Fulton
jim@zope.com
Thu, 23 May 2002 14:01:48 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/App/Traversing
In directory cvs.zope.org:/tmp/cvs-serv26429/lib/python/Zope/App/Traversing
Modified Files:
Tag: Zope-3x-branch
DefaultTraversable.py ITraversable.py Traverser.py
Added Files:
Tag: Zope-3x-branch
AcquireNamespace.py AttrItemNamespaces.py CreateNamespace.py
EtcNamespace.py Exceptions.py INamespaceHandler.py
Namespaces.py ParameterParsing.py PresentationNamespaces.py
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.
=== Added File Zope3/lib/python/Zope/App/Traversing/AcquireNamespace.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""
$Id: AcquireNamespace.py,v 1.1.2.1 2002/05/23 18:01:17 jim Exp $
"""
from Namespaces import provideNamespaceHandler
from Exceptions import UnexpectedParameters
from Zope.Exceptions import NotFoundError
from Zope.ComponentArchitecture import getAdapter
from Zope.Proxy.ContextWrapper import ContextWrapper, getWrapperContext
from ITraversable import ITraversable
class ExcessiveWrapping(NotFoundError):
"""Too many levels of acquisition wrapping. We don't believe them."""
def acquire(name, parameters, pname, ob, request):
if parameters:
raise UnexpectedParameters(parameters)
i = 0
origOb = ob
while i < 200:
i += 1
traversable = getAdapter(ob, ITraversable, None)
if traversable is not None:
try:
# XXX what do we do if the path gets bigger?
path = []
next = traversable.traverse(name, parameters, pname, path)
if path: continue
except NotFoundError:
pass
else:
return ContextWrapper(next, ob, name=name)
ob = getWrapperContext(ob)
if ob is None:
raise NotFoundError(origOb, pname)
raise ExcessiveWrapping(origOb, pname)
provideNamespaceHandler('acquire', acquire)
=== Added File Zope3/lib/python/Zope/App/Traversing/AttrItemNamespaces.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""
$Id: AttrItemNamespaces.py,v 1.1.2.1 2002/05/23 18:01:17 jim Exp $
"""
from Zope.ComponentArchitecture import getRequestView, getRequestResource
from Namespaces import provideNamespaceHandler
from Exceptions import UnexpectedParameters
def attr(name, parameters, pname, ob, request):
if parameters:
raise UnexpectedParameters(parameters)
return getattr(ob, name)
provideNamespaceHandler('attribute', attr)
def item(name, parameters, pname, ob, request):
if parameters:
raise UnexpectedParameters(parameters)
return ob[name]
provideNamespaceHandler('item', item)
# YAGNI
#
# def accessor(name, parameters, ob, request):
# if parameters:
# raise UnexpectedParameters(parameters)
#
# method = getattr(ob, name, None)
# if method is None:
# raise NotFound(ob, name, request)
#
# return method()
#
# provideNamespaceHandler('accessor', accessor)
=== Added File Zope3/lib/python/Zope/App/Traversing/CreateNamespace.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""
$Id: CreateNamespace.py,v 1.1.2.1 2002/05/23 18:01:17 jim Exp $
"""
from Zope.ComponentArchitecture import getService
from Namespaces import provideNamespaceHandler
from Exceptions import UnexpectedParameters
from Zope.Exceptions import NotFoundError
from Zope.Proxy.ContextWrapper import ContextWrapper
def create(name, parameters, pname, ob, request):
if parameters:
raise UnexpectedParameters(parameters)
for addable in getService(ob, 'AddableContent').getAddables(ob):
if addable.id == name:
return ContextWrapper(addable, ob, name=name)
raise NotFoundError(ob, pname)
provideNamespaceHandler('create', create)
=== Added File Zope3/lib/python/Zope/App/Traversing/EtcNamespace.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""
$Id: EtcNamespace.py,v 1.1.2.1 2002/05/23 18:01:17 jim Exp $
"""
from Zope.App.OFS.ApplicationControl.ApplicationControl \
import ApplicationController
from Namespaces import provideNamespaceHandler
from Exceptions import UnexpectedParameters
from Zope.Exceptions import NotFoundError
def etc(name, parameters, pname, ob, request):
# 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 parameters:
raise UnexpectedParameters(parameters)
if name == 'ApplicationController' and ob is None:
return ApplicationController
if name != 'Services':
raise NotFoundError(ob, pname, request)
method_name = "getServiceManager"
method = getattr(ob, method_name, None)
if method is None:
raise NotFound(ob, pname, request)
return method()
provideNamespaceHandler('etc', etc)
=== Added File Zope3/lib/python/Zope/App/Traversing/Exceptions.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""
$Id: Exceptions.py,v 1.1.2.1 2002/05/23 18:01:17 jim Exp $
"""
from Zope.Exceptions import NotFoundError
class UnexpectedParameters(NotFoundError):
"""Unexpected namespace parameters were provided.
"""
=== Added File Zope3/lib/python/Zope/App/Traversing/INamespaceHandler.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""
$Id: INamespaceHandler.py,v 1.1.2.1 2002/05/23 18:01:17 jim Exp $
"""
from Interface import Interface
class INamespaceHandler(Interface):
def __call__(name, parameters, pname, object, request):
"""Access a name in a namespace
The name lookup usually depends on an object and/or a
request. If an object or request is unavailable, None will be passed.
The parameters provided, are passed as a sequence of
name, value items. The 'pname' argument has the original name
before parameters were removed.
It is not the respoonsibility of the handler to wrap the return value.
"""
=== Added File Zope3/lib/python/Zope/App/Traversing/Namespaces.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""
$Id: Namespaces.py,v 1.1.2.1 2002/05/23 18:01:17 jim Exp $
"""
from Zope.Exceptions import NotFoundError
from Zope.Proxy.ContextWrapper import ContextWrapper
_namespace_handlers = {}
def provideNamespaceHandler(ns, handler):
_namespace_handlers[ns] = handler
def namespaceLookup(name, ns, qname, parameters, object, request=None):
"""Lookup a value from a namespace
name -- the original name
ns -- The namespace
qname -- The name without any parameters
"""
handler = _namespace_handlers.get(ns)
if handler is None:
raise NotFoundError(name)
new = ContextWrapper(handler(qname, parameters, name, object, request),
object, name=name)
return new
# Register the etc, view, and resource namespaces
import EtcNamespace, PresentationNamespaces, AttrItemNamespaces
=== Added File Zope3/lib/python/Zope/App/Traversing/ParameterParsing.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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
#
##############################################################################
"""
Revision information:
$Id: ParameterParsing.py,v 1.1.2.1 2002/05/23 18:01:17 jim Exp $
"""
class DuplicateNamespaces(Exception):
"""More than one namespace was specified in a request"""
def parameterizedNameParse(name):
"""Parse a name with parameters, including namespace parameters.
Return:
- namespace, or None if there isn't one.
- unparameterized name
- sequence of parameters, as name-value pairs.
"""
ns = ''
parts = name.split(';')
nm = parts[:1][0]
parms = ()
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:
parms += ((pname, pval),)
else:
if ns:
raise DuplicateNamespaces(name)
ns = param
return ns, nm, parms
=== Added File Zope3/lib/python/Zope/App/Traversing/PresentationNamespaces.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""
$Id: PresentationNamespaces.py,v 1.1.2.1 2002/05/23 18:01:17 jim Exp $
"""
from Zope.ComponentArchitecture import getRequestView, getRequestResource
from Namespaces import provideNamespaceHandler
from Exceptions import UnexpectedParameters
from Zope.Exceptions import NotFoundError
class NoRequest(NotFoundError):
"""Atempt to access a presentation component outside of a request context
"""
def view(name, parameters, pname, ob, request):
if parameters:
raise UnexpectedParameters(parameters)
if not request:
raise NoRequest(pname)
return getRequestView(ob, name, request)
provideNamespaceHandler('view', view)
def resource(name, parameters, pname, ob, request):
if parameters:
raise UnexpectedParameters(parameters)
if not request:
raise NoRequest(pname)
return getRequestResource(ob, name, request)
provideNamespaceHandler('resource', resource)
=== Zope3/lib/python/Zope/App/Traversing/DefaultTraversable.py 1.1.2.5 => 1.1.2.6 ===
from ITraversable import ITraversable
from Zope.Exceptions import NotFoundError
+from Exceptions import UnexpectedParameters
class DefaultTraversable:
"""Traverses objects via attribute and item lookup"""
@@ -22,7 +23,9 @@
def __init__(self, subject):
self._subject = subject
- def traverse(self, name, furtherPath):
+ def traverse(self, name, parameters, pname, furtherPath):
+ if parameters:
+ raise UnexpectedParameters(parameters)
subject = self._subject
r = getattr(subject, name, self) # self used as marker
if r is not self:
@@ -32,5 +35,5 @@
# Let exceptions propagate.
return self._subject[name]
else:
- raise NotFoundError, name
+ raise NotFoundError(self._subject, name)
=== Zope3/lib/python/Zope/App/Traversing/ITraversable.py 1.1.2.2 => 1.1.2.3 ===
"""To traverse an object, this interface must be provided"""
- def traverse(name, furtherPath):
+ def traverse(name, parameters, pname, furtherPath):
"""Get the next item on the path
- furtherPath is a list of names still to be traversed. This method is
- allowed to change the contents of furtherPath.
-
Should return the item corresponding to 'name' or raise
Zope.Exceptions.NotFoundError where appropriate.
+
+ The parameters provided, are passed as a sequence of
+ name, value items. The 'pname' argument has the original name
+ before parameters were removed.
+
+ furtherPath is a list of names still to be traversed. This method is
+ allowed to change the contents of furtherPath.
"""
=== Zope3/lib/python/Zope/App/Traversing/Traverser.py 1.1.2.10 => 1.1.2.11 ===
from Zope.ComponentArchitecture import getAdapter
from Zope.Exceptions import NotFoundError, Unauthorized
+from Namespaces import namespaceLookup
+from ParameterParsing import parameterizedNameParse
from Zope.Security.SecurityManagement import getSecurityManager
from types import StringTypes
@@ -42,9 +44,7 @@
__implements__ = ITraverser
- # XXX: This is wishful thinking, as it doesn't work like this yet
- # Arguably this feature should work for unwrapped objects as well.
- # __used_for__ = IWrapper
+ # This adapter can be used for any object.
def __init__(self, wrapper):
self._wrapper = wrapper
@@ -65,7 +65,7 @@
return tuple(path)
- def traverse(self, path, default=_marker):
+ def traverse(self, path, default=_marker, request=None):
if not path:
return self._wrapper
@@ -96,11 +96,22 @@
curr = getWrapperContext(curr) or curr
continue
+
+ if name.find(';') >= 0:
+ ns, nm, parms = parameterizedNameParse(name)
+ if ns:
+ curr = namespaceLookup(name, ns, nm, parms,
+ curr, request)
+ continue
+ else:
+ parms = ()
+ nm = name
+
traversable = getAdapter(curr, ITraversable, None)
if traversable is None:
raise NotFoundError, 'No traversable adapter found'
- next = traversable.traverse(name, path)
+ next = traversable.traverse(nm, parms, name, path)
curr = ContextWrapper(next, curr, name=name)
return curr
@@ -109,4 +120,5 @@
if default == _marker:
raise
return default
+