--- a/src/pyams_utils/traversing.py Sat Nov 23 01:24:11 2019 +0100
+++ b/src/pyams_utils/traversing.py Sat Nov 23 14:57:24 2019 +0100
@@ -10,7 +10,14 @@
# FOR A PARTICULAR PURPOSE.
#
-__docformat__ = 'restructuredtext'
+"""PyAMS_utils.traversing module
+
+This module provides a custom Pyramid "namespace" traverser: using "++name++" URLs allows
+to traverse URLs based on custom traversing adapters.
+
+It also provides a "get_parent" function, which returns a parent object of given object providing
+a given interface.
+"""
from pyramid.compat import decode_path_info, is_nonstr_iter
from pyramid.exceptions import NotFound, URLDecodeError
@@ -28,6 +35,9 @@
from pyams_utils.registry import query_utility
+__docformat__ = 'restructuredtext'
+
+
class NamespaceTraverser(ResourceTreeTraverser):
"""Custom traverser handling views and namespaces
@@ -41,7 +51,7 @@
NAMESPACE_SELECTOR = PLUS_SELECTOR * 2
def __call__(self, request):
-
+ # pylint: disable=too-many-locals,too-many-branches,too-many-statements
environ = request.environ
matchdict = request.matchdict
@@ -68,8 +78,8 @@
except KeyError:
# if environ['PATH_INFO'] is just not there
path = slash
- except UnicodeDecodeError as e:
- raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason)
+ except UnicodeDecodeError as exc:
+ raise URLDecodeError(exc.encoding, exc.object, exc.start, exc.end, exc.reason)
if VH_ROOT_KEY in environ:
# HTTP_X_VHM_ROOT
@@ -83,7 +93,7 @@
vroot_idx = -1
root = self.root
- ob = vroot = root
+ obj = vroot = root
request.registry.notify(BeforeTraverseEvent(root, request))
@@ -104,27 +114,28 @@
vpath_tuple = split_path_info(vpath)
for segment in vpath_tuple:
- if ob is not root:
- request.registry.notify(BeforeTraverseEvent(ob, request))
+ if obj is not root:
+ request.registry.notify(BeforeTraverseEvent(obj, request))
if segment == plus_selector:
# check for custom namespace called '+'
- # currently this namespace is used in PyAMS_default_theme package to get direct access to a given
- # content
+ # currently this namespace is used in PyAMS_default_theme package to get
+ # direct access to a given content
registry = get_current_registry()
- traverser = registry.queryMultiAdapter((ob, request), ITraversable, '+')
+ traverser = registry.queryMultiAdapter((obj, request), ITraversable, '+')
if traverser is None:
raise NotFound()
try:
- ob = traverser.traverse(vpath_tuple[vroot_idx + i + 2], vpath_tuple[vroot_idx + i + 3:])
+ obj = traverser.traverse(vpath_tuple[vroot_idx + i + 2],
+ vpath_tuple[vroot_idx + i + 3:])
except IndexError:
- # the "+" namespace traverser is waiting for additional elements from input URL
- # so a "+" URL not followed by something else is just an error!
+ # the "+" namespace traverser is waiting for additional elements from
+ # input URL so a "+" URL not followed by something else is just an error!
raise NotFound()
else:
i += 1
return {
- 'context': ob,
+ 'context': obj,
'view_name': ''.join(vpath_tuple[vroot_idx + i + 2:]),
'subpath': vpath_tuple[i + 2:],
'traversed': vpath_tuple[:vroot_idx + i + 2],
@@ -135,24 +146,25 @@
elif segment[:2] == ns_selector:
# check for namespace prefixed by '++'
- # when a namespace is detected, named "ITraversable" multi-adapters are searched for
- # context and request, or for context, sequentially; a NotFound exception is raised if traverser
- # can't be found, otherwise it's "traverse" method is called to get new context
- ns, name = segment[2:].split(ns_selector, 1)
+ # when a namespace is detected, named "ITraversable" multi-adapters are
+ # searched for context and request, or for context, sequentially; a NotFound
+ # exception is raised if traverser can't be found, otherwise it's "traverse"
+ # method is called to get new context
+ nss, name = segment[2:].split(ns_selector, 1)
registry = get_current_registry()
- traverser = registry.queryMultiAdapter((ob, request), ITraversable, ns)
+ traverser = registry.queryMultiAdapter((obj, request), ITraversable, nss)
if traverser is None:
- traverser = registry.queryAdapter(ob, ITraversable, ns)
+ traverser = registry.queryAdapter(obj, ITraversable, nss)
if traverser is None:
raise NotFound()
- ob = traverser.traverse(name, vpath_tuple[vroot_idx + i + 1:])
+ obj = traverser.traverse(name, vpath_tuple[vroot_idx + i + 1:])
i += 1
continue
elif segment[:2] == view_selector:
# check for view name prefixed by '@@'
return {
- 'context': ob,
+ 'context': obj,
'view_name': segment[2:],
'subpath': vpath_tuple[i + 1:],
'traversed': vpath_tuple[:vroot_idx + i + 1],
@@ -162,10 +174,10 @@
}
try:
- getitem = ob.__getitem__
+ getitem = obj.__getitem__
except AttributeError:
return {
- 'context': ob,
+ 'context': obj,
'view_name': segment,
'subpath': vpath_tuple[i + 1:],
'traversed': vpath_tuple[:vroot_idx + i + 1],
@@ -175,10 +187,10 @@
}
try:
- next = getitem(segment)
+ next_item = getitem(segment)
except KeyError:
return {
- 'context': ob,
+ 'context': obj,
'view_name': segment,
'subpath': vpath_tuple[i + 1:],
'traversed': vpath_tuple[:vroot_idx + i + 1],
@@ -187,15 +199,15 @@
'root': root
}
if i == vroot_idx:
- vroot = next
- ob = next
+ vroot = next_item
+ obj = next_item
i += 1
- if ob is not root:
- request.registry.notify(BeforeTraverseEvent(ob, request))
+ if obj is not root:
+ request.registry.notify(BeforeTraverseEvent(obj, request))
return {
- 'context': ob,
+ 'context': obj,
'view_name': empty,
'subpath': subpath,
'traversed': vpath_tuple,
@@ -210,10 +222,10 @@
:param object context: base element
:param Interface interface: the interface that parend should implement
- :param boolean allow_context: if 'True' (the default), traversing is done starting with context; otherwise,
- traversing is done starting from context's parent
- :param callable condition: an optional function that should return a 'True' result when called with parent
- as first argument
+ :param boolean allow_context: if 'True' (the default), traversing is done starting with
+ context; otherwise, traversing is done starting from context's parent
+ :param callable condition: an optional function that should return a 'True' result when
+ called with parent as first argument
"""
if allow_context:
parent = context
@@ -238,6 +250,7 @@
@property
def parents(self):
+ """Get list of parents OIDs"""
intids = query_utility(IIntIds)
if intids is None:
return []