Esempio n. 1
0
def traversePathElement(obj,
                        name,
                        further_path,
                        default=_marker,
                        traversable=None,
                        request=None):
    """Traverse a single step 'name' relative to the given object.

    'name' must be a string. '.' and '..' are treated specially, as well as
    names starting with '@' or '+'. Otherwise 'name' will be treated as a
    single path segment.

    'further_path' is a list of names still to be traversed.  This method
    is allowed to change the contents of 'further_path'.

    You can explicitly pass in an ITraversable as the 'traversable'
    argument. If you do not, the given object will be adapted to ITraversable.

    'request' is passed in when traversing from presentation code. This
    allows paths like @@foo to work.

    Raises LocationError if path cannot be found and 'default' was
    not provided.

    """
    __traceback_info__ = (obj, name)

    if name == '.':
        return obj

    if name == '..':
        return obj.__parent__

    if name and name[:1] in '@+':
        ns, nm = nsParse(name)
        if ns:
            return namespaceLookup(ns, nm, obj, request)
    else:
        nm = name

    if traversable is None:
        traversable = ITraversable(obj, None)
        if traversable is None:
            raise LocationError('No traversable adapter found', obj)

    try:
        return traversable.traverse(nm, further_path)
    except UnicodeEncodeError:
        # If we're on Python 2, and nm was a unicode string, and the traversable
        # tried to do an attribute lookup, the nm would have been encoded using the
        # system encoding (usually ascii). Failure to encode means invalid attribute
        # name.
        if default is not _marker:
            return default
        raise LocationError(obj, name)
    except LocationError:
        if default is not _marker:
            return default
        raise
Esempio n. 2
0
    def traverse(self, name, remaining):
        """
        Acquire a name

        Let's set up some example data::

          >>> @zope.interface.implementer(ITraversable)
          ... class testcontent(object):
          ...     def traverse(self, name, remaining):
          ...         v = getattr(self, name, None)
          ...         if v is None:
          ...             raise LocationError(self, name)
          ...         return v
          ...     def __repr__(self):
          ...         return 'splat'

          >>> ob = testcontent()
          >>> ob.a = 1
          >>> ob.__parent__ = testcontent()
          >>> ob.__parent__.b = 2
          >>> ob.__parent__.__parent__ = testcontent()
          >>> ob.__parent__.__parent__.c = 3

        And acquire some names:

          >>> adapter = acquire(ob)

          >>> adapter.traverse('a', ())
          1

          >>> adapter.traverse('b', ())
          2

          >>> adapter.traverse('c', ())
          3

          >>> adapter.traverse('d', ())
          Traceback (most recent call last):
          ...
          LocationError: (splat, 'd')
        """
        i = 0
        ob = self.context
        while i < 200:
            i += 1
            traversable = ITraversable(ob, None)
            if traversable is not None:
                try:
                    # ??? what do we do if the path gets bigger?
                    path = []
                    next = traversable.traverse(name, path)
                    if path:
                        continue
                except LocationError:
                    pass

                else:
                    return next

            ob = getattr(ob, '__parent__', None)
            if ob is None:
                raise LocationError(self.context, name)

        raise ExcessiveDepth(self.context, name)
Esempio n. 3
0
def traversePathElement(obj,
                        name,
                        further_path,
                        default=_marker,
                        traversable=None,
                        request=None):
    """
    Traverse a single step *name* relative to the given object.

    This is used to implement
    :meth:`zope.traversing.interfaces.ITraversalAPI.traverseName`.

    :param str name: must be a string.  '.' and '..' are treated
        specially, as well as names starting with '@' or '+'.
        Otherwise *name* will be treated as a single path segment.
    :param list further_path: a list of names still to be traversed.
        This method is allowed to change the contents of
        *further_path*.

    :keyword ITraversable traversable: You can explicitly pass in
        an `~zope.traversing.interfaces.ITraversable` as the
        *traversable* argument.  If you do not, the given object will
        be adapted to ``ITraversable``.

    :keyword request: assed in when traversing from presentation
        code.  This allows paths like ``@@foo`` to work.

    :raises zope.location.interfaces.LocationError: if *path* cannot
        be found and '*default* was not provided.
    """
    __traceback_info__ = (obj, name)

    if name == '.':
        return obj

    if name == '..':
        return obj.__parent__

    if name and name[:1] in '@+':
        ns, nm = nsParse(name)
        if ns:
            return namespaceLookup(ns, nm, obj, request)
    else:
        nm = name

    if traversable is None:
        traversable = ITraversable(obj, None)
        if traversable is None:
            raise LocationError('No traversable adapter found', obj)

    try:
        return traversable.traverse(nm, further_path)
    except UnicodeEncodeError:
        # If we're on Python 2, and nm was a unicode string, and the traversable
        # tried to do an attribute lookup, the nm would have been encoded using the
        # system encoding (usually ascii). Failure to encode means invalid attribute
        # name.
        if default is not _marker:
            return default
        raise LocationError(obj, name)
    except LocationError:
        if default is not _marker:
            return default
        raise