Exemplo n.º 1
0
    def traverseName(self, request, ob, name):
        nm = name  # the name to look up the object with

        if name and name[:1] in '@+':
            # Process URI segment parameters.
            ns, nm = nsParse(name)
            if ns:
                try:
                    ob2 = namespaceLookup(ns, nm, ob, request)
                except TraversalError:
                    raise NotFound(ob, name)

                return self.proxy(ob2)

        if nm == '.':
            return ob

        if IPublishTraverse.providedBy(ob):
            ob2 = ob.publishTraverse(request, nm)
        else:
            # self is marker
            adapter = queryMultiAdapter((ob, request), IPublishTraverse,
                                        default=self)
            if adapter is not self:
                ob2 = adapter.publishTraverse(request, nm)
            else:
                raise NotFound(ob, name, request)

        return self.proxy(ob2)
Exemplo n.º 2
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
Exemplo n.º 3
0
    def traverseName(self, request, ob, name):
        nm = name # the name to look up the object with

        if name and name[:1] in '@+':
            # Process URI segment parameters.
            ns, nm = nsParse(name)
            if ns:
                try:
                    ob2 = namespaceLookup(ns, nm, ob, request)
                except TraversalError:
                    raise NotFound(ob, name)

                return self.proxy(ob2)

        if nm == '.':
            return ob

        if IPublishTraverse.providedBy(ob):
            ob2 = ob.publishTraverse(request, nm)
        else:
            # self is marker
            adapter = queryMultiAdapter((ob, request), IPublishTraverse,
                                        default=self)
            if adapter is not self:
                ob2 = adapter.publishTraverse(request, nm)
            else:
                raise NotFound(ob, name, request)

        return self.proxy(ob2)
Exemplo n.º 4
0
    def traverseName(self, ob, name):
        if name and name[:1] in '@+':
            # Process URI segment parameters.
            ns, nm = nsParse(name)
            if ns:
                try:
                    ob2 = namespaceLookup(ns, nm, ob, self)
                except LocationError:
                    raise ztkNotFound(ob, name)

                if IAcquirer.providedBy(ob2):
                    ob2 = ob2.__of__(ob)
                return ob2

        if name == '.':
            return ob

        if IPublishTraverse.providedBy(ob):
            ob2 = ob.publishTraverse(self, name)
        else:
            adapter = queryMultiAdapter((ob, self), IPublishTraverse)
            if adapter is None:
                # Zope2 doesn't set up its own adapters in a lot of cases
                # so we will just use a default adapter.
                adapter = DefaultPublishTraverse(ob, self)

            ob2 = adapter.publishTraverse(self, name)

        return ob2
Exemplo n.º 5
0
    def traverseName(self, ob, name):
        if name and name[:1] in '@+':
            # Process URI segment parameters.
            ns, nm = nsParse(name)
            if ns:
                try:
                    ob2 = namespaceLookup(ns, nm, ob, self)
                except LocationError:
                    raise ztkNotFound(ob, name)

                if IAcquirer.providedBy(ob2):
                    ob2 = ob2.__of__(ob)
                return ob2

        if name == '.':
            return ob

        if IPublishTraverse.providedBy(ob):
            ob2 = ob.publishTraverse(self, name)
        else:
            adapter = queryMultiAdapter((ob, self), IPublishTraverse)
            if adapter is None:
                ## Zope2 doesn't set up its own adapters in a lot of cases
                ## so we will just use a default adapter.
                adapter = DefaultPublishTraverse(ob, self)

            ob2 = adapter.publishTraverse(self, name)

        return ob2
Exemplo n.º 6
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
Exemplo n.º 7
0
def patchedTraverseName(self, request, ob, name):
    nm = name # the name to look up the object with
    if name and name[:1] in '@+':
        # Process URI segment parameters.
        ns, nm = nsParse(name)
        if ns:
            try:
                ob2 = namespaceLookup(ns, nm, ob, request)
            except (TraversalError, ValueError), e:
                raise NotFound(ob, name)

            return ProxyFactory(ob2)
Exemplo n.º 8
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 LocationError:
        if default is not _marker:
            return default
        else:
            raise

    return obj
Exemplo n.º 9
0
    def traverseName(self, request, ob, name):
        bpth = getattr(object, '__before_publishing_traverse__', None)
        if bpth is not None:
            bpth(object, self)

        # mostly lifted from zope.app.publication.publicationtraverse
        lookup_name = name

        if name and name[:1] in '@+':
            # Process URI segment parameters.
            ns, lookup_name = nsParse(name)
            if ns:
                try:
                    subobject = namespaceLookup(ns, lookup_name, ob, request)
                except TraversalError:
                    raise NotFound(ob, name)

                return subobject

        if lookup_name == '.':
            return ob

        if IPublishTraverse.providedBy(ob):
            subobject = ob.publishTraverse(request, lookup_name)
        else:
            # self is marker
            adapter = queryMultiAdapter((ob, request),
                                        IPublishTraverse,
                                        default=self)
            if adapter is not self:
                subobject = adapter.publishTraverse(request, lookup_name)
            else:
                raise NotFound(ob, name, request)

        request['PARENTS'].append(subobject)
        return subobject
Exemplo n.º 10
0
    def unrestrictedTraverse(self, path, default=_marker, restricted=False):
        """Lookup an object by path.

        path -- The path to the object. May be a sequence of strings or a slash
        separated string. If the path begins with an empty path element
        (i.e., an empty string or a slash) then the lookup is performed
        from the application root. Otherwise, the lookup is relative to
        self. Two dots (..) as a path element indicates an upward traversal
        to the acquisition parent.

        default -- If provided, this is the value returned if the path cannot
        be traversed for any reason (i.e., no object exists at that path or
        the object is inaccessible).

        restricted -- If false (default) then no security checking is performed.
        If true, then all of the objects along the path are validated with
        the security machinery. Usually invoked using restrictedTraverse().
        """
        if not path:
            return self

        if isinstance(path, str):
            # Unicode paths are not allowed
            path = path.split('/')
        else:
            path = list(path)

        REQUEST = {'TraversalRequestNameStack': path}
        path.reverse()
        path_pop = path.pop

        if len(path) > 1 and not path[0]:
            # Remove trailing slash
            path_pop(0)

        if restricted:
            validate = getSecurityManager().validate

        if not path[-1]:
            # If the path starts with an empty string, go to the root first.
            path_pop()
            obj = self.getPhysicalRoot()
            if restricted:
                validate(None, None, None, obj) # may raise Unauthorized
        else:
            obj = self

        # import time ordering problem
        from webdav.NullResource import NullResource
        resource = _marker
        try:
            while path:
                name = path_pop()
                __traceback_info__ = path, name

                if name[0] == '_':
                    # Never allowed in a URL.
                    raise NotFound, name

                if name == '..':
                    next = aq_parent(obj)
                    if next is not None:
                        if restricted and not validate(obj, obj, name, next):
                            raise Unauthorized(name)
                        obj = next
                        continue

                bobo_traverse = getattr(obj, '__bobo_traverse__', None)
                try:
                    if name and name[:1] in '@+' and name != '+' and nsParse(name)[1]:
                        # Process URI segment parameters.
                        ns, nm = nsParse(name)
                        try:
                            next = namespaceLookup(
                                ns, nm, obj, aq_acquire(self, 'REQUEST'))
                            if IAcquirer.providedBy(next):
                                next = next.__of__(obj)
                            if restricted and not validate(
                                obj, obj, name, next):
                                raise Unauthorized(name)
                        except LocationError:
                            raise AttributeError(name)

                    else:
                        next = UseTraversalDefault # indicator
                        try:
                            if bobo_traverse is not None:
                                next = bobo_traverse(REQUEST, name)
                                if restricted:
                                    if aq_base(next) is not next:
                                        # The object is wrapped, so the acquisition
                                        # context is the container.
                                        container = aq_parent(aq_inner(next))
                                    elif getattr(next, 'im_self', None) is not None:
                                        # Bound method, the bound instance
                                        # is the container
                                        container = next.im_self
                                    elif getattr(aq_base(obj), name, _marker) is next:
                                        # Unwrapped direct attribute of the object so
                                        # object is the container
                                        container = obj
                                    else:
                                        # Can't determine container
                                        container = None
                                    # If next is a simple unwrapped property, its
                                    # parentage is indeterminate, but it may have
                                    # been acquired safely. In this case validate
                                    # will raise an error, and we can explicitly
                                    # check that our value was acquired safely.
                                    try:
                                        ok = validate(obj, container, name, next)
                                    except Unauthorized:
                                        ok = False
                                    if not ok:
                                        if (container is not None or
                                            guarded_getattr(obj, name, _marker)
                                                is not next):
                                            raise Unauthorized(name)
                        except UseTraversalDefault:
                            # behave as if there had been no '__bobo_traverse__'
                            bobo_traverse = None
                        if next is UseTraversalDefault:
                            if getattr(aq_base(obj), name, _marker) is not _marker:
                                if restricted:
                                    next = guarded_getattr(obj, name)
                                else:
                                    next = getattr(obj, name)
                            else:
                                try:
                                    next = obj[name]
                                    # The item lookup may return a NullResource,
                                    # if this is the case we save it and return it
                                    # if all other lookups fail.
                                    if isinstance(next, NullResource):
                                        resource = next
                                        raise KeyError(name)
                                except AttributeError:
                                    # Raise NotFound for easier debugging
                                    # instead of AttributeError: __getitem__
                                    raise NotFound(name)
                                if restricted and not validate(
                                    obj, obj, None, next):
                                    raise Unauthorized(name)

                except (AttributeError, NotFound, KeyError), e:
                    # Try to look for a view
                    next = queryMultiAdapter((obj, aq_acquire(self, 'REQUEST')),
                                             Interface, name)

                    if next is not None:
                        if IAcquirer.providedBy(next):
                            next = next.__of__(obj)
                        if restricted and not validate(obj, obj, name, next):
                            raise Unauthorized(name)
                    elif bobo_traverse is not None:
                        # Attribute lookup should not be done after
                        # __bobo_traverse__:
                        raise e
                    else:
                        # No view, try acquired attributes
                        try:
                            if restricted:
                                next = guarded_getattr(obj, name, _marker)
                            else:
                                next = getattr(obj, name, _marker)
                        except AttributeError:
                            raise e
                        if next is _marker:
                            # If we have a NullResource from earlier use it.
                            next = resource
                            if next is _marker:
                                # Nothing found re-raise error
                                raise e

                obj = next

            return obj
Exemplo n.º 11
0
    def unrestrictedTraverse(self, path, default=_marker, restricted=False):
        """Lookup an object by path.

        path -- The path to the object. May be a sequence of strings or a slash
        separated string. If the path begins with an empty path element
        (i.e., an empty string or a slash) then the lookup is performed
        from the application root. Otherwise, the lookup is relative to
        self. Two dots (..) as a path element indicates an upward traversal
        to the acquisition parent.

        default -- If provided, this is the value returned if the path cannot
        be traversed for any reason (i.e., no object exists at that path or
        the object is inaccessible).

        restricted -- If false (default) then no security checking is performed.
        If true, then all of the objects along the path are validated with
        the security machinery. Usually invoked using restrictedTraverse().
        """
        if not path:
            return self

        if isinstance(path, str):
            # Unicode paths are not allowed
            path = path.split('/')
        else:
            path = list(path)

        REQUEST = {'TraversalRequestNameStack': path}
        path.reverse()
        path_pop = path.pop

        if len(path) > 1 and not path[0]:
            # Remove trailing slash
            path_pop(0)

        if restricted:
            validate = getSecurityManager().validate

        if not path[-1]:
            # If the path starts with an empty string, go to the root first.
            path_pop()
            obj = self.getPhysicalRoot()
            if restricted:
                validate(None, None, None, obj)  # may raise Unauthorized
        else:
            obj = self

        # import time ordering problem
        from webdav.NullResource import NullResource
        resource = _marker
        try:
            while path:
                name = path_pop()
                __traceback_info__ = path, name

                if name[0] == '_':
                    # Never allowed in a URL.
                    raise NotFound, name

                if name == '..':
                    next = aq_parent(obj)
                    if next is not None:
                        if restricted and not validate(obj, obj, name, next):
                            raise Unauthorized(name)
                        obj = next
                        continue

                bobo_traverse = getattr(obj, '__bobo_traverse__', None)
                try:
                    if name and name[:1] in '@+' and name != '+' and nsParse(
                            name)[1]:
                        # Process URI segment parameters.
                        ns, nm = nsParse(name)
                        try:
                            next = namespaceLookup(ns, nm, obj,
                                                   aq_acquire(self, 'REQUEST'))
                            if IAcquirer.providedBy(next):
                                next = next.__of__(obj)
                            if restricted and not validate(
                                    obj, obj, name, next):
                                raise Unauthorized(name)
                        except LocationError:
                            raise AttributeError(name)

                    else:
                        next = UseTraversalDefault  # indicator
                        try:
                            if bobo_traverse is not None:
                                next = bobo_traverse(REQUEST, name)
                                if restricted:
                                    if aq_base(next) is not next:
                                        # The object is wrapped, so the acquisition
                                        # context is the container.
                                        container = aq_parent(aq_inner(next))
                                    elif getattr(next, 'im_self',
                                                 None) is not None:
                                        # Bound method, the bound instance
                                        # is the container
                                        container = next.im_self
                                    elif getattr(aq_base(obj), name,
                                                 _marker) is next:
                                        # Unwrapped direct attribute of the object so
                                        # object is the container
                                        container = obj
                                    else:
                                        # Can't determine container
                                        container = None
                                    # If next is a simple unwrapped property, its
                                    # parentage is indeterminate, but it may have
                                    # been acquired safely. In this case validate
                                    # will raise an error, and we can explicitly
                                    # check that our value was acquired safely.
                                    try:
                                        ok = validate(obj, container, name,
                                                      next)
                                    except Unauthorized:
                                        ok = False
                                    if not ok:
                                        if (container is not None
                                                or guarded_getattr(
                                                    obj, name,
                                                    _marker) is not next):
                                            raise Unauthorized(name)
                        except UseTraversalDefault:
                            # behave as if there had been no '__bobo_traverse__'
                            bobo_traverse = None
                        if next is UseTraversalDefault:
                            if getattr(aq_base(obj), name,
                                       _marker) is not _marker:
                                if restricted:
                                    next = guarded_getattr(obj, name)
                                else:
                                    next = getattr(obj, name)
                            else:
                                try:
                                    next = obj[name]
                                    # The item lookup may return a NullResource,
                                    # if this is the case we save it and return it
                                    # if all other lookups fail.
                                    if isinstance(next, NullResource):
                                        resource = next
                                        raise KeyError(name)
                                except (AttributeError, TypeError):
                                    # Raise NotFound for easier debugging
                                    # instead of AttributeError: __getitem__
                                    # or TypeError: not subscriptable
                                    raise NotFound(name)
                                if restricted and not validate(
                                        obj, obj, None, next):
                                    raise Unauthorized(name)

                except (AttributeError, NotFound, KeyError), e:
                    # Try to look for a view
                    next = queryMultiAdapter(
                        (obj, aq_acquire(self, 'REQUEST')), Interface, name)

                    if next is not None:
                        if IAcquirer.providedBy(next):
                            next = next.__of__(obj)
                        if restricted and not validate(obj, obj, name, next):
                            raise Unauthorized(name)
                    elif bobo_traverse is not None:
                        # Attribute lookup should not be done after
                        # __bobo_traverse__:
                        raise e
                    else:
                        # No view, try acquired attributes
                        try:
                            if restricted:
                                next = guarded_getattr(obj, name, _marker)
                            else:
                                next = getattr(obj, name, _marker)
                        except AttributeError:
                            raise e
                        if next is _marker:
                            # If we have a NullResource from earlier use it.
                            next = resource
                            if next is _marker:
                                # Nothing found re-raise error
                                raise e

                obj = next

            return obj
Exemplo n.º 12
0
    def getAllowedViews(self):
        """
        This method will return a dict containing the view name as keys
        and filesystem full path to both page template files and python
        files, according if it is a BrowserView or a FSPageTemplate
        """

        pt = getToolByName(self.context, 'portal_types')
        portal_type = self.context.portal_type
        dvt = pt[portal_type]

        result  = {}
        # The following was taken from traverseName function from
        # ZPublisher/BaseRequest.py
        for view in dvt.view_methods:
            if view[:1] in '@+':
                # Process URI segment parameters.
                ns, nm = nsParse(view)
                if ns:
                    try:
                        ob = namespaceLookup(ns, nm, self.context, self.request)
                    except TraversalError:
                        result[view] = {}
                        continue

                    if IAcquirer.providedBy(ob):
                        ob = ob.__of__(self.context)

            else:
                if IPublishTraverse.providedBy(self.context):
                    ob = self.context.publishTraverse(self.request, view)
                else:
                    adapter = queryMultiAdapter((self.context, self.request),
                                                IPublishTraverse)
                    if adapter is None:
                        ## Zope2 doesn't set up its own adapters in a lot of cases
                        ## so we will just use a default adapter.
                        adapter = DefaultPublishTraverse(self.context, self.request)

                    ob = adapter.publishTraverse(self.request, view)


            if isinstance(ob, BrowserView):
                # Taken from five.customerize.browser
                klass = ob.__class__
                base = klass.__bases__[0]
                if base is BrowserView or base is object:
                    py_file = inspect.getsourcefile(klass)
                else:
                    py_file = inspect.getsourcefile(base)
                pt_file = ob.index.filename

                result[view] = {'py':py_file,
                                'pt':pt_file}

            elif isinstance(ob, FSPageTemplate):
                result[view] = {'pt':ob.getObjectFSPath()}

            else:
                result[view] = {}


        return result
Exemplo n.º 13
0
def trustedTraverse(
    ob,
    path,
    ignored,
):
    if not path: return self

    get = getattr
    has = hasattr
    N = None
    M = rebindFunction  # artifical marker

    if isinstance(path, str): path = path.split('/')
    else: path = list(path)

    REQUEST = get(ob, 'REQUEST', None)
    if REQUEST is None:
        REQUEST = FakeRequest()
        setDefaultSkin(REQUEST)
    REQUEST['TraversalRequestNameStack'] = path
    path.reverse()
    pop = path.pop

    if len(path) > 1 and not path[0]:
        # Remove trailing slash
        path.pop(0)

    if not path[-1]:
        # If the path starts with an empty string, go to the root first.
        pop()
        self = ob.getPhysicalRoot()

    object = ob
    while path:
        name = pop()
        __traceback_info__ = path, name

        if name == '..':
            o = getattr(object, 'aq_parent', M)
            if o is not M:
                object = o
                continue

        if name and name[:1] in '@+':
            # Process URI segment parameters.
            ns, nm = nsParse(name)
            if ns:
                try:
                    o = namespaceLookup(ns, nm, object, REQUEST).__of__(object)
                except TraversalError:
                    raise KeyError(name)
                object = o
                continue

        t = get(object, '__bobo_traverse__', M)
        if t is not M: o = t(REQUEST, name)
        else:
            o = get(object, name, M)
            if o is M:
                try:
                    o = object[name]
                except (AttributeError, TypeError):  # better exception
                    o = queryMultiAdapter((object, REQUEST), Interface, name)
                    if o is not None:
                        o = o.__of__(object)
                    else:
                        raise AttributeError(name)
        object = o

    return object
Exemplo n.º 14
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