Metadata-Version: 1.0
Name: plone.namedfile
Version: 1.0b5
Summary: File types tand fields for images, files and blob files with filenames
Home-page: http://pypi.python.org/pypi/plone.namedfile
Author: Laurence Rowe, Martin Aspeli
Author-email: plone-developers@lists.sourceforge.net
License: GPL
Description: Introduction
        ============
        
        This package contains fields and wrapper objects for storing:
        
        * A file with a filename
        * An image with a filename
        
        BLOB based types are supported if the z3c.blobfile package is installed.
        This will also require the ZODB3 package to be at version 3.8.1 or later,
        and BLOBs to be configured in zope.conf.
        
        One way to make sure that z3c.blobfile is installed is to depend on the
        [blobs] extra to this package, e.g.::
        
        install_requires = [
        ...
        'plone.namedfile[blobs]',
        ]
        
        plone.supermodel handlers are registered if plone.supermodel is installed.
        The [supermodel] extra will ensure this.
        
        See the usage.txt doctest for more details.
        
        Changelog
        =========
        
        1.0b5 - 2010-04-19
        ------------------
        
        * Add support for scaled images.  See usage.txt for details.
        [davisagli]
        
        * Fix the field schemata so they can be used as the form schema when
        adding the field using plone.schemaeditor.
        [rossp]
        
        1.0b4 - 2009-11-17
        ------------------
        
        * Avoid using the internal _current_filename() helper, which disappeared in
        ZODB 3.9.
        [optilude]
        
        * Add field factories for plone.schemaeditor (only installed if
        plone.schemaeditor is available)
        [davisagli]
        
        1.0b3 - 2009-10-08
        ------------------
        
        * Add plone.rfc822 field marshaler (only installed if plone.rfc822 is
        available)
        [optilude]
        
        1.0b2 - 2009-09-17
        ------------------
        
        * Add plone.supermodel import/export handlers (only installed if
        plone.supermodel is available).
        [optilude]
        
        1.0b1 - 2009-05-30
        ------------------
        
        * Make z3c.blobfile (and blobs in general) a soft dependency. You'll need to
        separately depend on z3c.blobfile (and probably pin it to versio 0.1.2) to
        get the NamedBlobFile and NamedBlobImage fields. This means that
        plone.namedfile can be used with ZODB versions that do not support BLOBs.
        This policy will probably be revisited for a 2.0 release.
        [optilude]
        
        1.0a1 - 2009-04-17
        ------------------
        
        * Initial release
        
        
        Usage
        =====
        
        This demonstrates how to use the package. In this instance, we will assume
        that z3c.blobfile is installed so that BLOB based types are supported.
        
        Test setup
        ----------
        
        We must first load the package's ZCML.
        
        >>> configuration = """\
        ... <configure
        ...      xmlns="http://namespaces.zope.org/zope"
        ...      i18n_domain="plone.namedfile.tests">
        ...
        ...     <include package="plone.namedfile" />
        ...
        ... </configure>
        ... """
        
        >>> from StringIO import StringIO
        >>> from zope.configuration import xmlconfig
        >>> xmlconfig.xmlconfig(StringIO(configuration))
        
        Schema fields
        -------------
        
        The following schema fields can be used to describe file data. We'll only
        test the BLOB versions of the fields if z3c.blobfile is installed.
        
        >>> from zope.interface import Interface
        >>> from plone.namedfile import field
        >>> from plone.namedfile.interfaces import HAVE_BLOBS
        
        >>> class IFileContainer(Interface):
        ...     simple = field.NamedFile(title=u"Named file")
        ...     image = field.NamedImage(title=u"Named image file")
        ...     if HAVE_BLOBS:
        ...         blob = field.NamedBlobFile(title=u"Named blob file")
        ...         blobimage = field.NamedBlobImage(title=u"Named blob image file")
        
        These store data with the following types.
        
        >>> from zope.interface import implements
        >>> from plone import namedfile
        
        >>> class FileContainer(object):
        ...     implements(IFileContainer)
        ...     def __init__(self):
        ...         self.simple = namedfile.NamedFile()
        ...         self.image = namedfile.NamedImage()
        ...         if HAVE_BLOBS:
        ...             self.blob = namedfile.NamedBlobFile()
        ...             self.blobimage = namedfile.NamedBlobImage()
        
        File data and content type
        --------------------------
        
        Let's now show how to get and set file data.
        
        The FileContainer class creates empty objects to start with.
        
        >>> container = FileContainer()
        
        >>> container.simple.data
        ''
        >>> container.simple.contentType
        ''
        >>> container.simple.filename is None
        True
        
        >>> container.image.data
        ''
        >>> container.image.contentType
        ''
        >>> container.image.filename is None
        True
        
        >>> if HAVE_BLOBS:
        ...     print repr(container.blob.data)
        ...     print repr(container.blob.contentType)
        ...     print repr(container.blob.filename is None)
        ...     print repr(container.blobimage.data)
        ...     print repr(container.blobimage.contentType)
        ...     print repr(container.blobimage.filename is None)
        ... else:
        ...     print repr('')
        ...     print repr('')
        ...     print repr(True)
        ...     print repr('')
        ...     print repr('')
        ...     print repr(True)
        ''
        ''
        True
        ''
        ''
        True
        
        Let's now set some actual data in these files. Notice how the constructor
        will attempt to guess the filename from the file extension.
        
        >>> container.simple = namedfile.NamedFile('dummy test data', filename="test.txt")
        >>> container.simple.data
        'dummy test data'
        >>> container.simple.contentType
        'text/plain'
        >>> container.simple.filename
        'test.txt'
        
        >>> if HAVE_BLOBS:
        ...     container.blob = namedfile.NamedBlobFile('dummy test data', filename="test.txt")
        ...     print repr(container.blob.data)
        ...     print repr(container.blob.contentType)
        ...     print repr(container.blob.filename)
        ... else:
        ...     print repr('dummy test data')
        ...     print repr('text/plain')
        ...     print repr('test.txt')
        'dummy test data'
        'text/plain'
        'test.txt'
        
        Let's also try to read a GIF, courtesy of the zope.app.file tests:
        
        >>> zptlogo = (
        ...     'GIF89a\x10\x00\x10\x00\xd5\x00\x00\xff\xff\xff\xff\xff\xfe\xfc\xfd\xfd'
        ...     '\xfa\xfb\xfc\xf7\xf9\xfa\xf5\xf8\xf9\xf3\xf6\xf8\xf2\xf5\xf7\xf0\xf4\xf6'
        ...     '\xeb\xf1\xf3\xe5\xed\xef\xde\xe8\xeb\xdc\xe6\xea\xd9\xe4\xe8\xd7\xe2\xe6'
        ...     '\xd2\xdf\xe3\xd0\xdd\xe3\xcd\xdc\xe1\xcb\xda\xdf\xc9\xd9\xdf\xc8\xd8\xdd'
        ...     '\xc6\xd7\xdc\xc4\xd6\xdc\xc3\xd4\xda\xc2\xd3\xd9\xc1\xd3\xd9\xc0\xd2\xd9'
        ...     '\xbd\xd1\xd8\xbd\xd0\xd7\xbc\xcf\xd7\xbb\xcf\xd6\xbb\xce\xd5\xb9\xcd\xd4'
        ...     '\xb6\xcc\xd4\xb6\xcb\xd3\xb5\xcb\xd2\xb4\xca\xd1\xb2\xc8\xd0\xb1\xc7\xd0'
        ...     '\xb0\xc7\xcf\xaf\xc6\xce\xae\xc4\xce\xad\xc4\xcd\xab\xc3\xcc\xa9\xc2\xcb'
        ...     '\xa8\xc1\xca\xa6\xc0\xc9\xa4\xbe\xc8\xa2\xbd\xc7\xa0\xbb\xc5\x9e\xba\xc4'
        ...     '\x9b\xbf\xcc\x98\xb6\xc1\x8d\xae\xbaFgs\x00\x00\x00\x00\x00\x00\x00\x00'
        ...     '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
        ...     '\x00,\x00\x00\x00\x00\x10\x00\x10\x00\x00\x06z@\x80pH,\x12k\xc8$\xd2f\x04'
        ...     '\xd4\x84\x01\x01\xe1\xf0d\x16\x9f\x80A\x01\x91\xc0ZmL\xb0\xcd\x00V\xd4'
        ...     '\xc4a\x87z\xed\xb0-\x1a\xb3\xb8\x95\xbdf8\x1e\x11\xca,MoC$\x15\x18{'
        ...     '\x006}m\x13\x16\x1a\x1f\x83\x85}6\x17\x1b $\x83\x00\x86\x19\x1d!%)\x8c'
        ...     '\x866#\'+.\x8ca`\x1c`(,/1\x94B5\x19\x1e"&*-024\xacNq\xba\xbb\xb8h\xbeb'
        ...     '\x00A\x00;'
        ...     )
        
        >>> container.image = namedfile.NamedImage(zptlogo, filename="zpt.gif")
        >>> container.image.data == zptlogo
        True
        >>> container.image.contentType
        'image/gif'
        >>> container.image.filename
        'zpt.gif'
        
        >>> if HAVE_BLOBS:
        ...     container.blobimage = namedfile.NamedBlobImage(zptlogo, filename="zpt.gif")
        ...     print repr(container.blobimage.data == zptlogo)
        ...     print repr(container.blobimage.contentType)
        ...     print repr(container.blobimage.filename)
        ... else:
        ...     print repr(True)
        ...     print repr('image/gif')
        ...     print repr('zpt.gif')
        True
        'image/gif'
        'zpt.gif'
        
        Note that is possible for force the mimetype:
        
        >>> container.image = namedfile.NamedImage(zptlogo, contentType='image/foo', filename="zpt.gif")
        >>> container.image.data == zptlogo
        True
        >>> container.image.contentType
        'image/foo'
        >>> container.image.filename
        'zpt.gif'
        
        >>> if HAVE_BLOBS:
        ...     container.blobimage = namedfile.NamedBlobImage(zptlogo, contentType='image/foo', filename="zpt.gif")
        ...     print repr(container.blobimage.data == zptlogo)
        ...     print repr(container.blobimage.contentType)
        ...     print repr(container.blobimage.filename)
        ... else:
        ...     print repr(True)
        ...     print repr('image/foo')
        ...     print repr('zpt.gif')
        True
        'image/foo'
        'zpt.gif'
        
        Download view
        -------------
        
        This package also comes with a view that can be used to download files. To
        use it, link to ../context-object/@@download/fieldname, where `fieldname` is
        the name of the attribute on the context-object where the named file is
        stored.
        
        We will test this with a dummy request, faking traversal.
        
        >>> from plone.namedfile.browser import Download
        >>> from zope.publisher.browser import TestRequest
        
        >>> request = TestRequest()
        >>> download = Download(container, request).publishTraverse(request, 'simple')
        >>> download()
        'dummy test data'
        >>> request.response.getHeader('Content-Length')
        '15'
        >>> request.response.getHeader('Content-Type')
        'text/plain'
        >>> request.response.getHeader('Content-Disposition')
        'attachment; filename="test.txt"'
        
        >>> if HAVE_BLOBS:
        ...     request = TestRequest()
        ...     download = Download(container, request).publishTraverse(request, 'blob')
        ...     data = download()
        ...     print repr(isinstance(data, file))
        ...     print repr(data.read())
        ...     print repr(request.response.getHeader('Content-Length'))
        ...     print repr(request.response.getHeader('Content-Type'))
        ...     print repr(request.response.getHeader('Content-Disposition'))
        ... else:
        ...     print repr(True)
        ...     print repr('dummy test data')
        ...     print repr('15')
        ...     print repr('text/plain')
        ...     print repr('attachment; filename="test.txt"')
        True
        'dummy test data'
        '15'
        'text/plain'
        'attachment; filename="test.txt"'
        
        >>> request = TestRequest()
        >>> download = Download(container, request).publishTraverse(request, 'image')
        >>> download() == zptlogo
        True
        
        >>> request.response.getHeader('Content-Length')
        '341'
        >>> request.response.getHeader('Content-Type')
        'image/foo'
        >>> request.response.getHeader('Content-Disposition')
        'attachment; filename="zpt.gif"'
        
        >>> request = TestRequest()
        >>> if HAVE_BLOBS:
        ...     download = Download(container, request).publishTraverse(request, 'blobimage')
        ...     data = download()
        ...     print repr(isinstance(data, file))
        ...     print repr(data.read() == zptlogo)
        ...     print repr(request.response.getHeader('Content-Length'))
        ...     print repr(request.response.getHeader('Content-Type'))
        ...     print repr(request.response.getHeader('Content-Disposition'))
        ... else:
        ...     print repr(True)
        ...     print repr(True)
        ...     print repr('341')
        ...     print repr('image/foo')
        ...     print repr('attachment; filename="zpt.gif"')
        True
        True
        '341'
        'image/foo'
        'attachment; filename="zpt.gif"'
        
        Image scales
        ------------
        
        This package can handle the creation, storage, and retrieval of arbitrarily
        sized scaled versions of images stored in NamedImage or NamedBlobImage fields.
        
        Image scales are accessed via an @@images view that is available for any item
        providing ``plone.namedfile.interfaces.IImageScaleTraversable``.  There are
        several ways that you may reference scales from page templates.
        
        1. for full control you may do the tag generation explicitly::
        
        <img tal:define="scales context/@@images;
        thumbnail python: scales.scale('image', width=64, height=64);"
        tal:condition="thumbnail"
        tal:attributes="src thumbnail/url;
        width thumbnail/width;
        height thumbnail/height" />
        
        This would create an up to 64 by 64 pixel scaled down version of the image
        stored in the "image" field.  It also allows for passing in additional
        parameters support by `plone.scale`_'s ``scaleImage`` function, e.g.
        ``direction`` or ``quality``.
        
        .. _`plone.scale`: http://pypi.python.org/pypi/plone.scale
        
        2. for automatic tag generation with extra parameters you would use::
        
        <img tal:define="scale context/@@images"
        tal:replace="structure python: scale.scale('image',
        width=1200, height=800, direction='down').tag()" />
        
        3. It is possible to access scales via predefined named scale sizes, rather
        than hardcoding the dimensions every time you access a scale.  The scale
        sizes are found via calling a utility providing
        ``plone.namedfile.interfaces.IAvailableSizes``, which should return a dict of
        scale name => (width, height).  A scale called 'mini' could then be accessed
        like this::
        
        <img tal:define="scale context/@@images"
        tal:replace="structure python: scale.scale('image',
        scale='mini').tag()" />
        
        This would use the predefined scale size "mini" to determine the desired
        image dimensions, but still allow to pass in extra parameters.
        
        4. a convenience short-cut for option 3 can be used::
        
        <img tal:replace="structure context/@@images/image/mini" />
        
        5. and lastly, the short-cut can also be used to render the unscaled image::
        
        <img tal:replace="structure context/@@images/image" />
        
Keywords: plone named file image blob
Platform: UNKNOWN
Classifier: Framework :: Plone
Classifier: Programming Language :: Python
Classifier: Topic :: Software Development :: Libraries :: Python Modules
