[Zope3-checkins] CVS: Zope3/src/zope/app/traversing - adapters.py:1.1 namespace.py:1.1 __init__.py:1.5 configure.zcml:1.4 meta.zcml:1.3 acquirenamespace.py:NONE attritemnamespaces.py:NONE defaulttraversable.py:NONE etcnamespace.py:NONE exceptions.py:NONE getresource.py:NONE modulenamespace.py:NONE namespaces.py:NONE objectname.py:NONE parameterparsing.py:NONE physicallocationadapters.py:NONE presentationnamespaces.py:NONE skinnamespace.py:NONE traverser.py:NONE
Steve Alexander
steve@cat-box.net
Sat, 28 Dec 2002 12:50:04 -0500
Update of /cvs-repository/Zope3/src/zope/app/traversing
In directory cvs.zope.org:/tmp/cvs-serv912/src/zope/app/traversing
Modified Files:
__init__.py configure.zcml meta.zcml
Added Files:
adapters.py namespace.py
Removed Files:
acquirenamespace.py attritemnamespaces.py
defaulttraversable.py etcnamespace.py exceptions.py
getresource.py modulenamespace.py namespaces.py objectname.py
parameterparsing.py physicallocationadapters.py
presentationnamespaces.py skinnamespace.py traverser.py
Log Message:
Compressed various independent modules in zope.app.traversing into
far fewer modules.
Also, changed the place where the textindex lives to one level higher.
=== Added File Zope3/src/zope/app/traversing/adapters.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: adapters.py,v 1.1 2002/12/28 17:49:33 stevea Exp $
"""
from zope.exceptions import NotFoundError
from zope.app.interfaces.traversing import IObjectName, IPhysicallyLocatable
from zope.app.interfaces.traversing import IContainmentRoot
from zope.app.interfaces.traversing import ITraverser, ITraversable
from zope.component import getAdapter, queryAdapter
from zope.proxy.context import getInnerWrapperData, getWrapperContainer
from zope.proxy.context import ContextWrapper
from zope.app.traversing.namespace import namespaceLookup
from zope.app.traversing.namespace import UnexpectedParameters
from zope.app.traversing.namespace import parameterizedNameParse
from types import StringTypes
__metaclass__ = type
_marker = object() # opaque marker that doesn't get security proxied
class DefaultTraversable:
"""Traverses objects via attribute and item lookup"""
__implements__ = ITraversable
def __init__(self, subject):
self._subject = subject
def traverse(self, name, parameters, pname, furtherPath):
if parameters:
raise UnexpectedParameters(parameters)
subject = self._subject
r = getattr(subject, name, _marker)
if r is not _marker:
return r
if hasattr(subject, '__getitem__'):
# Let exceptions propagate.
return self._subject[name]
else:
raise NotFoundError(self._subject, name)
class ObjectName(object):
__implements__ = IObjectName
def __init__(self, context):
self.context = context
def __str__(self):
dict = getInnerWrapperData(self.context)
name = dict and dict.get('name') or None
if name is None:
raise TypeError, \
'Not enough context information to get an object name'
return name
__call__ = __str__
class SiteObjectName(object):
__implements__ = IObjectName
def __init__(self, context):
pass
def __str__(self):
return ''
__call__ = __str__
class WrapperPhysicallyLocatable:
__doc__ = IPhysicallyLocatable.__doc__
__implements__ = IPhysicallyLocatable
def __init__(self, context):
self.context = context
def getPhysicalRoot(self):
"See IPhysicallyLocatable"
container = getWrapperContainer(self.context)
if container is None:
raise TypeError("Not enough context to determine location root")
return getAdapter(container, IPhysicallyLocatable).getPhysicalRoot()
def getPhysicalPath(self):
"See IPhysicallyLocatable"
context = self.context
container = getWrapperContainer(context)
if container is None:
raise TypeError("Not enough context to determine location")
name = getInnerWrapperData(context)['name']
container = getAdapter(container, IPhysicallyLocatable)
container_path = container.getPhysicalPath()
if name == '.':
# skip
return container_path
return container_path + (name, )
class RootPhysicallyLocatable:
__doc__ = IPhysicallyLocatable.__doc__
__implements__ = IPhysicallyLocatable
__used_for__ = IContainmentRoot
def __init__(self, context):
self.context = context
def getPhysicalPath(self):
"See IPhysicallyLocatable"
return ('', )
def getPhysicalRoot(self):
"See IPhysicallyLocatable"
return self.context
class Traverser:
"""Provide traverse features"""
__implements__ = ITraverser
# This adapter can be used for any object.
def __init__(self, wrapper):
self.context = wrapper
def traverse(self, path, default=_marker, request=None):
if not path:
return self.context
if isinstance(path, StringTypes):
path = path.split('/')
if len(path) > 1 and not path[-1]:
# Remove trailing slash
path.pop()
else:
path = list(path)
path.reverse()
pop = path.pop
curr = self.context
if not path[-1]:
# Start at the root
pop()
curr = getAdapter(self.context, IPhysicallyLocatable
).getPhysicalRoot()
try:
while path:
name = pop()
if name == '.':
continue
if name == '..':
# XXX This doesn't look right. Why fall back to curr?
curr = getWrapperContainer(curr) or curr
continue
if name and name[:1] in '@+':
ns, nm, parms = parameterizedNameParse(name)
if ns:
curr = namespaceLookup(name, ns, nm, parms,
curr, request)
continue
else:
parms = ()
nm = name
traversable = queryAdapter(curr, ITraversable, None)
if traversable is None:
raise NotFoundError(
'No traversable adapter found', curr)
next = traversable.traverse(nm, parms, name, path)
curr = ContextWrapper(next, curr, name=name)
return curr
except NotFoundError:
if default == _marker:
raise
return default
=== Added File Zope3/src/zope/app/traversing/namespace.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: namespace.py,v 1.1 2002/12/28 17:49:33 stevea Exp $
"""
from zope.interface import Interface
from zope.exceptions import NotFoundError
from zope.proxy.context import ContextWrapper, getWrapperObject
from zope.proxy.context import getWrapperContext
from zope.configuration.action import Action
from zope.component import queryAdapter, getAdapter, getServiceManager
from zope.component import queryDefaultViewName, getView, getService
from zope.app.interfaces.traversing import ITraversable
from zope.app.applicationcontrol.applicationcontrol \
import applicationController
from zope.app.content.folder import RootFolder
from zope.app.interfaces.services.service import INameResolver
import re
class UnexpectedParameters(NotFoundError):
"Unexpected namespace parameters were provided."
class ExcessiveWrapping(NotFoundError):
"Too many levels of acquisition wrapping. We don't believe them."
class NoRequest(NotFoundError):
"Attempt to access a presentation component outside of a request context."
_namespace_handlers = {}
def provideNamespaceHandler(ns, handler):
_namespace_handlers[ns] = handler
def directive(_context, name, handler):
handler = _context.resolve(handler)
return [Action(
discriminator=("traversalNamespace", name),
callable=provideNamespaceHandler,
args=(name, 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
The resulting object is returned in the context of the original.
This means that the caller should *not* wrap the result.
"""
handler = _namespace_handlers.get(ns)
if handler is None:
raise NotFoundError(name)
new = handler(qname, parameters, name, object, request)
if new is object:
# The handler had a side effect only and didn't look up a
# different object. We want to retain the side-effect name
# for things like URLs.
# But wait, there's more. The object may be wrapped. If the
# object is already wrapped and we return the object in the
# context of itself, the containment context will be wrong,
# because the inner wrapper will be the original object, so
# our added layer with the name we want to preserve will be
# ignored when searching containment.
# For this reason, we'll remove a layer of wrapping from new
# before we put it in context.
new = getWrapperObject(new)
new = ContextWrapper(new, object, name='.', side_effect_name=name)
else:
new = ContextWrapper(new, object, name=name)
return new
namespace_pattern = re.compile('[+][+]([a-zA-Z0-9_]+)[+][+]')
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 = ''
if name.startswith('@@'):
ns = 'view'
name = name[2:]
else:
match = namespace_pattern.match(name)
if match:
prefix, ns = match.group(0, 1)
name = name[len(prefix):]
return ns, name, ()
def getResourceInContext(ob, name, request):
resource = queryResourceInContext(ob, name, request)
if resource is None:
raise NotFoundError(ob, name)
return resource
def queryResourceInContext(ob, name, request, default=None):
resource_service = getService(ob, 'Resources')
resource = resource_service.queryResource(ob, name, request)
if resource is None:
return default
return ContextWrapper(resource, resource_service, name=name)
# ---- namespace processors below ----
def acquire(name, parameters, pname, ob, request):
if parameters:
raise UnexpectedParameters(parameters)
i = 0
origOb = ob
while i < 200:
i += 1
traversable = queryAdapter(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)
def attr(name, parameters, pname, ob, request):
if parameters:
raise UnexpectedParameters(parameters)
return getattr(ob, name)
def item(name, parameters, pname, ob, request):
if parameters:
raise UnexpectedParameters(parameters)
return ob[name]
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.__class__ == RootFolder:
return applicationController
if name != 'Services':
raise NotFoundError(ob, pname, request)
method_name = "getServiceManager"
method = getattr(ob, method_name, None)
if method is None:
raise NotFoundError(ob, pname, request)
return method()
def module(name, parameters, pname, ob, request):
"""Used to traverse to a module (in dot notation)"""
servicemanager = getServiceManager(ob)
adapter = getAdapter(servicemanager, INameResolver)
if adapter is not None:
ob = adapter.resolve(name)
if queryDefaultViewName(ob, request) is None:
return Interface
return ob
def view(name, parameters, pname, ob, request):
if parameters:
raise UnexpectedParameters(parameters)
if not request:
raise NoRequest(pname)
return getView(ob, name, request)
def resource(name, parameters, pname, ob, request):
if parameters:
raise UnexpectedParameters(parameters)
if not request:
raise NoRequest(pname)
resource = queryResourceInContext(ob, name, request)
if resource is None:
raise NotFoundError(ob, pname)
return resource
def skin(name, parameters, pname, ob, request):
if parameters:
raise UnexpectedParameters(parameters)
if not request:
raise NoRequest(pname)
request.setViewSkin(name)
return ob
=== Zope3/src/zope/app/traversing/__init__.py 1.4 => 1.5 ===
--- Zope3/src/zope/app/traversing/__init__.py:1.4 Sat Dec 28 10:20:50 2002
+++ Zope3/src/zope/app/traversing/__init__.py Sat Dec 28 12:49:33 2002
@@ -12,13 +12,15 @@
#
##############################################################################
"""
-Traversing the object tree.
+Convenience functions for traversing the object tree.
"""
from zope.component import getAdapter
from zope.app.interfaces.traversing import IObjectName, IContainmentRoot
from zope.app.interfaces.traversing import ITraverser, IPhysicallyLocatable
-from zope.app.traversing.traverser import WrapperChain, Traverser
+# XXX moved to later on to avoid byzantine circular import
+#from zope.app.traversing.adapters import Traverser
from zope.proxy.context import getWrapperContext, isWrapper
+from zope.proxy.context import getWrapperContainer
from types import StringTypes
__all__ = ['traverse', 'traverseName', 'objectName', 'getParent',
@@ -45,6 +47,7 @@
code unexpectedly.
Consider using traverseName instead.
"""
+ from zope.app.traversing.adapters import Traverser
traverser = Traverser(place)
if default is _marker:
return traverser.traverse(path, request=request)
@@ -100,9 +103,14 @@
if IContainmentRoot.isImplementedBy(obj):
return []
if isWrapper(obj):
- iterator = WrapperChain(obj)
- iterator.next() # send head of chain (current object) to /dev/null
- parents = [p for p in iterator]
+ parents = []
+ w = obj
+ while 1:
+ w = getWrapperContainer(w)
+ if w is None:
+ break
+ parents.append(w)
+
if parents and IContainmentRoot.isImplementedBy(parents[-1]):
return parents
raise TypeError, "Not enough context information to get all parents"
=== Zope3/src/zope/app/traversing/configure.zcml 1.3 => 1.4 ===
--- Zope3/src/zope/app/traversing/configure.zcml:1.3 Sat Dec 28 10:35:27 2002
+++ Zope3/src/zope/app/traversing/configure.zcml Sat Dec 28 12:49:33 2002
@@ -3,47 +3,70 @@
xmlns:browser='http://namespaces.zope.org/browser'
>
-<adapter factory="zope.app.traversing.traverser.Traverser"
+<adapter factory="zope.app.traversing.adapters.Traverser"
provides="zope.app.interfaces.traversing.ITraverser"
/>
<!-- Ultimately, this should be registered only for IWrapper, but that
won't work like that just now.
for="zope.proxy.interfaces.context.IWrapper" /> -->
-<adapter factory="zope.app.traversing.defaulttraversable.DefaultTraversable"
+<adapter factory="zope.app.traversing.adapters.DefaultTraversable"
provides="zope.app.interfaces.traversing.ITraversable" />
<adapter
- factory="zope.app.traversing.objectname.ObjectName"
- provides="zope.app.traversing.objectname.IObjectName"
+ factory="zope.app.traversing.adapters.ObjectName"
+ provides="zope.app.interfaces.traversing.IObjectName"
permission='zope.Public'
/>
<adapter
- factory="zope.app.traversing.objectname.SiteObjectName"
- provides="zope.app.traversing.objectname.IObjectName"
+ factory="zope.app.traversing.adapters.SiteObjectName"
+ provides="zope.app.interfaces.traversing.IObjectName"
for="zope.app.interfaces.content.folder.IRootFolder"
permission='zope.Public'
/>
<adapter
provides="zope.app.interfaces.traversing.IPhysicallyLocatable"
- factory="zope.app.traversing.physicallocationadapters.WrapperPhysicallyLocatable"
+ factory="zope.app.traversing.adapters.WrapperPhysicallyLocatable"
/>
<adapter
provides="zope.app.interfaces.traversing.IPhysicallyLocatable"
for="zope.app.interfaces.traversing.IContainmentRoot"
- factory="zope.app.traversing.physicallocationadapters.RootPhysicallyLocatable"
+ factory="zope.app.traversing.adapters.RootPhysicallyLocatable"
/>
-<traversalNamespace name="etc" handler="zope.app.traversing.etcnamespace.etc" />
-<traversalNamespace name="view" handler="zope.app.traversing.presentationnamespaces.view" />
-<traversalNamespace name="resource"
- handler="zope.app.traversing.presentationnamespaces.resource" />
-<traversalNamespace name="attribute" handler="zope.app.traversing.attritemnamespaces.attr" />
-<traversalNamespace name="item" handler="zope.app.traversing.attritemnamespaces.item" />
-<traversalNamespace name="acquire" handler="zope.app.traversing.acquirenamespace.acquire" />
-<traversalNamespace name="skin" handler="zope.app.traversing.skinnamespace.skin" />
-<traversalNamespace name="module" handler="zope.app.traversing.modulenamespace.module" />
+<traversalNamespace
+ name="etc"
+ handler="zope.app.traversing.namespace.etc"
+ />
+<traversalNamespace
+ name="view"
+ handler="zope.app.traversing.namespace.view"
+ />
+<traversalNamespace
+ name="resource"
+ handler="zope.app.traversing.namespace.resource"
+ />
+<traversalNamespace
+ name="attribute"
+ handler="zope.app.traversing.namespace.attr"
+ />
+<traversalNamespace
+ name="item"
+ handler="zope.app.traversing.namespace.item"
+ />
+<traversalNamespace
+ name="acquire"
+ handler="zope.app.traversing.namespace.acquire"
+ />
+<traversalNamespace
+ name="skin"
+ handler="zope.app.traversing.namespace.skin"
+ />
+<traversalNamespace
+ name="module"
+ handler="zope.app.traversing.namespace.module"
+ />
</zopeConfigure>
=== Zope3/src/zope/app/traversing/meta.zcml 1.2 => 1.3 ===
--- Zope3/src/zope/app/traversing/meta.zcml:1.2 Wed Dec 25 09:13:26 2002
+++ Zope3/src/zope/app/traversing/meta.zcml Sat Dec 28 12:49:33 2002
@@ -3,7 +3,7 @@
<directives namespace="http://namespaces.zope.org/zope">
<directive name="traversalNamespace" attributes="name handler"
- handler="zope.app.traversing.namespaces.directive" />
+ handler="zope.app.traversing.namespace.directive" />
</directives>
=== Removed File Zope3/src/zope/app/traversing/acquirenamespace.py ===
=== Removed File Zope3/src/zope/app/traversing/attritemnamespaces.py ===
=== Removed File Zope3/src/zope/app/traversing/defaulttraversable.py ===
=== Removed File Zope3/src/zope/app/traversing/etcnamespace.py ===
=== Removed File Zope3/src/zope/app/traversing/exceptions.py ===
=== Removed File Zope3/src/zope/app/traversing/getresource.py ===
=== Removed File Zope3/src/zope/app/traversing/modulenamespace.py ===
=== Removed File Zope3/src/zope/app/traversing/namespaces.py ===
=== Removed File Zope3/src/zope/app/traversing/objectname.py ===
=== Removed File Zope3/src/zope/app/traversing/parameterparsing.py ===
=== Removed File Zope3/src/zope/app/traversing/physicallocationadapters.py ===
=== Removed File Zope3/src/zope/app/traversing/presentationnamespaces.py ===
=== Removed File Zope3/src/zope/app/traversing/skinnamespace.py ===
=== Removed File Zope3/src/zope/app/traversing/traverser.py ===