Welcome, guest | Sign In | My Account | Store | Cart

Notice! PyPM is being replaced with the ActiveState Platform, which enhances PyPM’s build and deploy capabilities. Create your free Platform account to download ActivePython or customize Python with the packages you require and get automatic updates.

Download
ActivePython
INSTALL>
pypm install dolmen.thumbnailer

How to install dolmen.thumbnailer

  1. Download and install ActivePython
  2. Open Command Prompt
  3. Type pypm install dolmen.thumbnailer
 Python 2.7Python 3.2Python 3.3
Windows (32-bit)
0.3 Available View build log
Windows (64-bit)
0.3 Available View build log
Mac OS X (10.5+)
0.3 Available View build log
Linux (32-bit)
0.3 Available View build log
Linux (64-bit)
0.3 Available View build log
 
License
GPL
Lastest release
version 0.3 on Jan 5th, 2011

dolmen.thumbnailer is package specialized in Thumbnail generation. Using the dolmen.storage mechanisms, it allows a pluggable and flexible thumbnail storage.

Thumbnailer

The thumbnailer is the component in charge of effectively scaling down the image. This component is defined by the IThumbnailer interface:

>>> from dolmen.thumbnailer import IThumbnailer
>>> print IThumbnailer['scale'].__doc__

System Message: ERROR/3 (<string>, line 18)

Inconsistent literal block quoting.

Returns a StringIO that is a data representation of an image, scaled down to the given size.

Out-of-the-box, an IThumbnailer implementation is proposed, as an adapter. In order to test it, we need both a model and an image. The model will serve as a base for the adaptation:

>>> fd = open(IMAGE_PATH, 'r')
>>> data = fd.read()
>>> fd.close()
>>> class BasicContent(object):
...   pass
>>> mycontext = BasicContent()
>>> thumbnailer = IThumbnailer(mycontext)
>>> thumbnailer
<dolmen.thumbnailer.components.ScaleThumbnailer object at ...>

We can now test the scaling method. This method, as specified in the IThumbnailer interface, requires the data, given as a PIL Image, and a scale (a tuple of width and height):

>>> from PIL import Image
>>> from cStringIO import StringIO
>>> image = Image.open(StringIO(data))
>>> scale = thumbnailer.scale(image, (100, 100))
>>> scale
<cStringIO.StringO object at ...>
>>> Image.open(scale).size
(100, 100)

The scale method returns a cStringIO.StringIO that can be used to recreate a PIL.Image or to save in an object, as a binary string.

This implementation of IThumbnailer is not modifying the original image:

>>> image.size

System Message: ERROR/3 (<string>, line 59)

Inconsistent literal block quoting.

(280, 280)

The thumbnailer handles some basic errors for you:

>>> thumbnailer.scale(None, (100, 100))

System Message: ERROR/3 (<string>, line 64)

Inconsistent literal block quoting.

Traceback (most recent call last): ... TypeError: Scaling can only occur using a PIL Image

>>> thumbnailer.scale(image, None)
Traceback (most recent call last):
...
ValueError: Size must be a (width, height) tuple

System Message: ERROR/3 (<string>, line 73)

Content block expected for the "attention" directive; none found.

.. attention::

The next component, the Miniaturizer, will query a named IThumbnailer for each thumbnail scale, using the scale name. If no named IThumbnailer is found, it fallbacks to the base one.

Miniaturizer

The Miniaturizer is the component in charge of the thumbnailing policy. It handles the name and size, the storage class used as the file-wrapper and provides a collection of methods to manage the generation, retrieval and deletion of the thumbnails.

Default policy

The default policy is defined in the interface IImageMiniaturizer, implemented by the Miniaturizer component. Let's have a quick overview:

>>> from dolmen.thumbnailer import IImageMiniaturizer
>>> print IImageMiniaturizer['scales'].default
{'large': (700, 700), 'mini': (250, 250), 'small': (128, 128), 'preview': (400, 400), 'thumb': (150, 150)}
>>> print IImageMiniaturizer['factory'].default
<class 'dolmen.file.file.NamedFile'>
Storage and adapter

Out-of-the-box, dolmen.thumbnailer provides a IImageMiniaturizer implementation as an adapter. While it uses the default scales and factory, it queries a dolmen.storage.IDelegatedStorage component for the storage. This storage is a dolmen.storage.AnnotationStorage named 'thumbnail', in order to write the store the thumbnails in the object annotations.

This means, we need a IAttributeAnnotatable object:

>>> miniaturizer = IImageMiniaturizer(mycontext)

System Message: ERROR/3 (<string>, line 117)

Inconsistent literal block quoting.

Traceback (most recent call last): ... TypeError: ('Could not adapt', <BasicContent object at ...>, <InterfaceClass dolmen.thumbnailer.interfaces.IImageMiniaturizer>)

>>> from zope.annotation import IAttributeAnnotatable
>>> from zope.interface import alsoProvides
>>> alsoProvides(mycontext, IAttributeAnnotatable)
>>> miniaturizer = IImageMiniaturizer(mycontext)
>>> miniaturizer
<dolmen.thumbnailer.components.Miniaturizer object at ...>

Now we obtain a Miniaturizer object. We can verify its conformity with the interface that describes it:

>>> from zope.interface import verify
>>> verify.verifyObject(IImageMiniaturizer, miniaturizer)

System Message: ERROR/3 (<string>, line 134)

Inconsistent literal block quoting.

True

>>> miniaturizer.storage
<dolmen.thumbnailer.components.ThumbnailStorage object at ...>
>>> from dolmen.storage import IDelegatedStorage
>>> IDelegatedStorage.providedBy(miniaturizer.storage)
True
Generation

The Miniaturizer assumes that your data is stored on a field of the object. The methods provided by the component will use the fieldname to trigger their action.

Let's add an image attribute to our content object:

>>> from dolmen.file import file
>>> mycontext.image = file.NamedFile(data=data)
>>> mycontext.image

System Message: ERROR/3 (<string>, line 156)

Inconsistent literal block quoting.

<dolmen.file.file.NamedFile object at ...>

Our image is persisted on our object, in an attribute called 'image'. Let's trigger the thumbnails generation:

>>> miniaturizer.generate(fieldname="image")

System Message: ERROR/3 (<string>, line 162)

Inconsistent literal block quoting.

True

The return value is a boolean representing the success of the generation. Let's have a look at our storage, after the generation:

>>> list(miniaturizer.storage.keys())

System Message: ERROR/3 (<string>, line 168)

Inconsistent literal block quoting.

['image.large', 'image.mini', 'image.preview', 'image.small', 'image.thumb']

Some errors are handled for you:

>>> miniaturizer.generate(fieldname="nonexisting")

System Message: ERROR/3 (<string>, line 173)

Inconsistent literal block quoting.

False

>>> miniaturizer.generate(fieldname="__class__")
Traceback (most recent call last):
...
IOError: cannot identify image file
Retrieval

The thumbnails can be retrieved easily, using the scale name and the field name:

>>> scale = miniaturizer.retrieve('mini', fieldname="image")
>>> scale

System Message: ERROR/3 (<string>, line 189)

Inconsistent literal block quoting.

<dolmen.file.file.NamedFile object at ...>

As we can see, the thumbnails data is wrapped in a dolmen.file.file.NamedFile object, which is the factory defined in your default policy:

>>> isinstance(scale, IImageMiniaturizer['factory'].default)

System Message: ERROR/3 (<string>, line 196)

Inconsistent literal block quoting.

True

The Miniaturizer can fetch a thumbnail using a "fieldname.scalename" key:

>>> print miniaturizer['image.mini']

System Message: ERROR/3 (<string>, line 202)

Inconsistent literal block quoting.

<dolmen.file.file.NamedFile object at ...>

>>> print miniaturizer.get('image.small')
<dolmen.file.file.NamedFile object at ...>
>>> print miniaturizer.get('image.nonexistance')
None
>>> print miniaturizer.get('image.nonexistance', 'nothing !')
nothing !

As usual, some error situations are handled for you:

>>> print miniaturizer.retrieve('manfred', fieldname="image")

System Message: ERROR/3 (<string>, line 215)

Inconsistent literal block quoting.

None >>> print miniaturizer.retrieve('manfred', fieldname="not there") None

Deletion

The deletion action will use the fieldname to delete all the thumbnails generated for the given field:

>>> miniaturizer.delete(fieldname="image")
>>> list(miniaturizer.storage.keys())

System Message: ERROR/3 (<string>, line 228)

Inconsistent literal block quoting.

[]

Access and security

The thumbnails are generated and stored. Logically, we now want to publish the thumbnails in order to make them accessible through a URL. The dolmen.thumbnailer provides a traverser based on dolmen.file.access.FilePublisher:

>>> from zope.component import getMultiAdapter
>>> from zope.publisher.browser import TestRequest
>>> from zope.traversing.interfaces import ITraversable
>>> miniaturizer.generate(fieldname="image")
True
>>> request = TestRequest()
>>> traverser = getMultiAdapter((mycontext, request),
...                             ITraversable, name='thumbnail')

The basic permission used to check the availability of the data is zope.View. We set up two principals to test this. 'jason' is a logged in member with no rights, while 'judith' has the zope.View permission granted:

>>> import zope.security.management as security
>>> from zope.security.testing import Principal, Participation
>>> judith = Principal('zope.judith', 'Judith')
>>> jason = Principal('zope.jason', 'Jason')

We create the interaction and try to traverse to our thumbnail:

>>> security.newInteraction(Participation(jason))
>>> traverser.traverse('image.small')

System Message: ERROR/3 (<string>, line 265)

Inconsistent literal block quoting.

Traceback (most recent call last): ... Unauthorized: image.small >>> security.endInteraction()

It fails. An Unauthorized Error is raised. We now try with Judith:

>>> security.newInteraction(Participation(judith))
>>> traverser.traverse('image.small')

System Message: ERROR/3 (<string>, line 274)

Inconsistent literal block quoting.

<dolmen.file.access.FilePublisher object at ...> >>> security.endInteraction()

Our thumbnail is returned, wrapped in a FilePublisher view, which is ready to be rendered (see dolmen.file access documentation for more information).

Changelog

0.3 (2010-02-27)
  • Cleaned dependencies. We no longer have zope.app dependencies.
  • We now use dolmen.file.file.File as base files for the thumbnails.
0.2.3 (2010-02-19)
  • Corrected the PIL version to 1.1.7
0.2.2 (2010-02-19)
  • Updated dependency : PILwoTK to PIL.
0.2.1 (2009-10-25)
  • Updated to the latest version of dolmen.field.
0.2 (2009-10-23)
  • Now thumbnails can be named, if the factory implements

System Message: WARNING/2 (<string>, line 315)

Bullet list ends without a blank line; unexpected unindent.

dolmen.file.INamedFile.

  • Corrected a bug where the specified mimeType was not a valid one.
0.1 (2009-10-21)
  • Initial release

Subscribe to package updates

Last updated Jan 5th, 2011

Download Stats

Last month:3

What does the lock icon mean?

Builds marked with a lock icon are only available via PyPM to users with a current ActivePython Business Edition subscription.

Need custom builds or support?

ActivePython Enterprise Edition guarantees priority access to technical support, indemnification, expert consulting and quality-assured language builds.

Plan on re-distributing ActivePython?

Get re-distribution rights and eliminate legal risks with ActivePython OEM Edition.