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
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
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
def path_traverse(base, econtext, call, path_items): if path_items: request = econtext.get("request") path_items = list(path_items) path_items.reverse() while path_items: name = path_items.pop() ns_used = ":" in name if ns_used: namespace, name = name.split(":", 1) base = z3c.pt.namespaces.function_namespaces[namespace](base) if ITraversable.providedBy(base): base = traversePathElement(base, name, path_items, request=request) # base = proxify(base) continue # special-case dicts for performance reasons if isinstance(base, dict): next = base.get(name, _marker) else: next = getattr(base, name, _marker) if next is not _marker: base = next if ns_used and isinstance(base, MethodType): base = base() # The bytecode peephole optimizer removes the next line: continue # pragma: no cover else: base = traversePathElement(base, name, path_items, request=request) # if not isinstance(base, (basestring, tuple, list)): # base = proxify(base) if call and getattr(base, "__call__", _marker) is not _marker: return base() return base
def path_traverse(base, econtext, call, path_items): if path_items: request = econtext.get('request') path_items = list(path_items) path_items.reverse() while len(path_items): name = path_items.pop() ns_used = ':' in name if ns_used: namespace, name = name.split(':', 1) base = z3c.pt.namespaces.function_namespaces[namespace](base) if ITraversable.providedBy(base): base = traversePathElement(base, name, path_items, request=request) # base = proxify(base) continue # special-case dicts for performance reasons if isinstance(base, dict): next = base.get(name, _marker) else: next = getattr(base, name, _marker) if next is not _marker: base = next if ns_used and isinstance(base, MethodType): base = base() continue else: base = traversePathElement(base, name, path_items, request=request) # if not isinstance(base, (basestring, tuple, list)): # base = proxify(base) if call and getattr(base, '__call__', _marker) is not _marker: return base() return base
def path_traverse(base, econtext, call, path_items): if path_items: request = econtext.get("request") path_items = list(path_items) path_items.reverse() while path_items: name = path_items.pop() ns_used = ":" in name if ns_used: namespace, name = name.split(":", 1) base = z3c.pt.namespaces.function_namespaces[namespace](base) if ITraversable.providedBy(base): base = traversePathElement( base, name, path_items, request=request ) # base = proxify(base) continue # special-case dicts for performance reasons if isinstance(base, dict): next = base.get(name, _marker) else: next = getattr(base, name, _marker) if next is not _marker: base = next if ns_used and isinstance(base, MethodType): base = base() # The bytecode peephole optimizer removes the next line: continue # pragma: no cover else: base = traversePathElement( base, name, path_items, request=request ) # if not isinstance(base, (basestring, tuple, list)): # base = proxify(base) if call and getattr(base, "__call__", _marker) is not _marker: return base() return base
def path_traverse(base, econtext, call, path_items): if path_items: request = econtext.get('request') path_items = list(path_items) path_items.reverse() while len(path_items): name = path_items.pop() ns_used = ':' in name if ns_used: namespace, name = name.split(':', 1) base = z3c.pt.namespaces.function_namespaces[namespace](base) if ITraversable.providedBy(base): base = traversePathElement( base, name, path_items, request=request) # base = proxify(base) continue # special-case dicts for performance reasons if isinstance(base, dict): next = base.get(name, _marker) else: next = getattr(base, name, _marker) if next is not _marker: base = next if ns_used and isinstance(base, MethodType): base = base() continue else: base = traversePathElement( base, name, path_items, request=request) # if not isinstance(base, (basestring, tuple, list)): # base = proxify(base) if call and getattr(base, '__call__', _marker) is not _marker: return base() return base
def testImplementsITraversable(self): self.assertTrue(ITraversable.providedBy(DefaultTraversable(None)))
def traverse(self, name, remaining): """Acquire a name Let's set up some example data: >>> class testcontent(object): ... zope.interface.implements(ITraversable) ... 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)
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)
def testImplementsITraversable(self): self.failUnless(ITraversable.providedBy(DefaultTraversable(None)))
def __call__(self, text, file_path=None): dom = getDom(text) if not dom: return text for link in dom.cssselect('a[href],img[src]'): link = LinkElement(link) url = link.val.rstrip('/').strip() match_path = url.replace('%20', ' ').lstrip('/').strip() if type(match_path) == unicode: match_path = match_path.encode('utf-8') obj = self.context.unrestrictedTraverse(match_path, None) ext = match_path.split('.')[-1].lower() ext = ext in ('png', 'jpg', 'gif', 'jpeg') and ext or 'jpg' if obj and isinstance(obj, ATImage) or ( hasattr(obj, 'getBlobWrapper') and \ 'image' in obj.getBlobWrapper().getContentType()): link.set(url + '/image.%s' % ext) elif obj and isinstance(obj, ArchetypesImage): # it's a scale, always use image.jpg extension link.set(url + '/image.jpg') if not obj: try: path, filename = match_path.rsplit('/', 1) except ValueError: continue fieldname = filename.split('_', 1)[0] obj = self.context.restrictedTraverse('/'.join((path, fieldname)), None) if not obj: # not all fields are traversable obj = self.context.restrictedTraverse(path, None) if IImageScaling.providedBy(obj) or \ ITraversable.providedBy(obj): # we can't do anything with the @@images view yet here... obj = None if obj and hasattr(obj, 'getField'): field = obj.getField(fieldname) if field: obj = field.get(obj) if PLONE_APP_BLOB_INSTALLED and IBlobWrapper.providedBy(obj): link.set(url + '/image.jpg') if not obj: if '/@@images/' in match_path: parent_path, image_name = match_path.split('/@@images/') spl_img_name = image_name.split('/') if len(spl_img_name) == 1: # no scalename in path uid = spl_img_name[0] if '-' in uid: # seems to be actual uid for a custom scale here... # it should written out as [uid].[ext] new_path = '/'.join((parent_path, uid)) else: # just use original if we can't figure this out... new_path = '/'.join((parent_path, 'image.%s' % ext)) else: # scalename in path fieldname, scalename = spl_img_name new_path = '/'.join((parent_path, '_'.join((fieldname, scalename)))) new_path = new_path + '/image.jpg' new_path = '/' + new_path.lstrip('/') link.set(new_path) return unicode(dom)
def __call__(self, request): # pylint:disable=too-many-locals,too-many-branches,too-many-statements """ See :meth:`pyramid.interfaces.ITraversar.__call__`. """ # JAM: Unfortunately, the superclass implementation is entirely monolithic # and we so we cannot reuse any part of it. Instead, # we copy-and-paste it. Unless otherwise noted, comments below are # original. # JAM: Note the abundance of no covers. These are for features we are # not currently using and the code is lifted directly from pyramid. environ = request.environ if request.matchdict is not None: matchdict = request.matchdict path = matchdict.get('traverse', '/') or '/' if is_nonstr_iter(path): # this is a *traverse stararg (not a {traverse}) # routing has already decoded these elements, so we just # need to join them path = '/'.join(path) or '/' subpath = matchdict.get('subpath', ()) if not is_nonstr_iter(subpath): # pragma: no cover # this is not a *subpath stararg (just a {subpath}) # routing has already decoded this string, so we just need # to split it subpath = split_path_info(subpath) else: # pragma: no cover # this request did not match a route subpath = () try: # empty if mounted under a path in mod_wsgi, for example path = decode_path_info(environ['PATH_INFO'] or '/') except KeyError: path = '/' except UnicodeDecodeError as e: raise URLDecodeError(e.encoding, e.object, e.start, e.end, e.reason) if VH_ROOT_KEY in environ: # pragma: no cover # HTTP_X_VHM_ROOT vroot_path = decode_path_info(environ[VH_ROOT_KEY]) vroot_tuple = split_path_info(vroot_path) # both will (must) be unicode or asciistr vpath = vroot_path + path vroot_idx = len(vroot_tuple) - 1 else: vroot_tuple = () vpath = path vroot_idx = -1 root = self.root ob = vroot = root if vpath == '/': # invariant: vpath must not be empty # prevent a call to traversal_path if we know it's going # to return the empty tuple vpath_tuple = () else: i = 0 view_selector = self.VIEW_SELECTOR # A list so that remaining_path can be modified vpath_tuple = list(split_path_info(vpath)) for segment in vpath_tuple: # JAM: Fire traversal events, mainly so sites get installed. See # zope.publisher.base. _notify_before_traverse_event(ob, request) # JAM: Notice that checking for '@@' is special cased, and # doesn't go through the normal namespace lookup as it would in # plain zope traversal. (XXX: Why not?) if segment.startswith(view_selector): # pragma: no cover return { 'context': ob, 'view_name': segment[2:], 'subpath': vpath_tuple[i + 1:], 'traversed': vpath_tuple[:vroot_idx + i + 1], 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root } try: # JAM: This is where we differ. instead of using __getitem__, # we use the traversing machinery. # The zope app would use IPublishTraverser, which # would install security proxies along the way. We probably don't need to # do that? TODO: # NOTE: By passing the request here, we require all traversers # (including the namespace traversers) to be registered as multi-adapters. # None of the default namespaces are. See our # configure.zcml for what is. # JAM: Damn stupid implementation of traversePathElement ignores # the request argument to find a traversable /except/ when a namespace is found. # therefore, we explicitly query for the multi adapter ourself in the non-namespace case # (In the namespace case, we let traversing handle it, because it needs a named adapter # after parsing) traversable = None if segment and segment[0] not in '+@' \ and not ITraversable.providedBy(ob): try: # Use the installed component registry # instead of the request registry (which # is the global component registry if # pyramid was configured that way, or a # standalone registry) in case the act of # traversing has changed the site manager; # zope.site.site.threadSiteSubscriber will # do this for each BeforeTraverseEvent # that's fired (though that's not # registered by default). traversable = queryMultiAdapter((ob, request), ITraversable) except TypeError: # Some things are registered for "*" (DefaultTraversable) # which means they get called here. If they can't take # two arguments, then we bail. Sucks. pass remaining_path = vpath_tuple[i + 1:] next_ob = ztraversing.traversePathElement( ob, segment, remaining_path, traversable=traversable, request=request) if remaining_path != vpath_tuple[i + 1:]: # Is this if check necessary? It would be faster to # always assign vpath_tuple[i + 1:] = remaining_path except LocationError: # LocationError is a type of KeyError. The DefaultTraversable turns # plain KeyError and TypeErrors into LocationError. return { 'context': ob, 'view_name': segment, 'subpath': vpath_tuple[i + 1:], 'traversed': vpath_tuple[:vroot_idx + i + 1], 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root } if i == vroot_idx: # pragma: no cover vroot = next_ob ob = next_ob i += 1 # JAM: Also fire before traversal for the actual context item, since we # won't actually traverse into it. Be sure not to fire multiple times # for this (E.g., the root). This logic is complicated by the # multi-returns above. _notify_before_traverse_event(ob, request) return { 'context': ob, 'view_name': empty, 'subpath': subpath, 'traversed': vpath_tuple, 'virtual_root': vroot, 'virtual_root_path': vroot_tuple, 'root': root }