Thierry FLORAC wrote:
> Hi,
> I'm trying to build a sample photos management application for Zope-3.2,
> with the following interfaces and classes :

>  - class GalleryFolder(Folder)
>      def getImages(self):
>        return [item for item in self.values() 
>                              if IGalleryPhoto.providedBy(item)]

The list object you're returning here will be security proxied because
it's returned to a view.

>  - class Gallery(GalleryFolder, SiteManagerContainer)
>      ...
> Until now, it's OK !
> After that, I created a sample view based on a page template for
> IGalleryFolder, using a view class :
>   - <tal:x repeat="image view/getImages"> ... </tal:x>
>   - class FolderInfo:
>       def getImages(self):
>         """Get a sorted list of images"""
>         result = IGalleryFolder(self.context).getImages()
>         result.sort (lambda x,y: cmp(IGalleryPhoto(x).name,
>                                      IGalleryPhoto(y).name))
>         return result

As said above, 'result' will be security proxied. Security proxies for
lists only allow methods that don't change the lists. result.sort()
would change it. Hence it's forbidden.

An easy workaround is to use sorted():

  result = IGalleryFolder(self.context).getImages()
  return sorted(result, cmp=...)

Note that using 'cmp' is very slow. It's much faster to use 'key':

  result = IGalleryFolder(self.context).getImages()
  return sorted(result, key=lambda x: IGalleryPhoto(x).name)

With this, sorted() will use IGalleryPhoto(...).name of each item as a
sort key. The lambda expession will only be called once for every
object. A 'cmp' function would be called many more times.

> But when trying to display the view, a ForbiddenAttribute exception is
> raised :
>   File ".../browser/", line 39, in getImages
>     result.sort (lambda x,y:
>                  cmp(IGalleryPhoto(x).name,IGalleryPhoto(y).name))
>   ForbiddenAttribute:('sort',[<GalleryPhoto object at 0xa5b378ac>,...] 
> So the forbidden attribute seems to be the "sort" method of the
> resulting array, which of course isn't part of any of my interfaces.

Nitpick: This isn't an array, it's a list. There's a big difference
between those two (lists can contain arbitrary objects, for example).


Zope3-users mailing list

Reply via email to