{ "info": { "author": "Zope Community", "author_email": "zope-dev@zope.org", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: Zope3", "Intended Audience :: Developers", "License :: OSI Approved :: Zope Public License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Internet :: WWW/HTTP" ], "description": "Blob File\n=========\n\nThis package provides an implementation of zope.app.file.interfaces.IFile\nwhich uses the Blob support introduced in ZODB 3.8. It's main purpose\nis to provide an easy migration path for existing instances. For more\nadvanced file implementations see zope.file and z3c.extfile. \n\nThe standard implementation in zope.app.file uses chunk objects to\nbreak big files into manageable parts. These chunks flow the server caches \nwhereas blobs are directly consumed by the publisher. The main difference\nbetween this blob implementation and the old zope.app.file implementation\ncan be seen in a replacement of the chunk objects by Blobs.\n\n\nDetailed Documentation\n----------------------\n\n\nBlob File Implementation\n========================\n\nThis implementation of zope.app.file.interfaces.IFile takes advantage\nof the new ZODB blob support and tries to be completely backward compatible to\nthe existing file implementation in zope.app.file.\n\nCompatibility with zope.app.file.File\n-------------------------------------\n\nThe following tests mimic exactly the tests of the zope.app.file package.\n\nLet's test the constructor:\n\n >>> from zope.app.file import File, Image\n\n >>> file = File()\n >>> file.contentType\n ''\n >>> file.data\n ''\n\n >>> file = File('Foobar')\n >>> file.contentType\n ''\n >>> file.data\n 'Foobar'\n\n >>> file = File('Foobar', 'text/plain')\n >>> file.contentType\n 'text/plain'\n >>> file.data\n 'Foobar'\n\n >>> file = File(data='Foobar', contentType='text/plain')\n >>> file.contentType\n 'text/plain'\n >>> file.data\n 'Foobar'\n\n\nLet's test the mutators:\n\n >>> file = File()\n >>> file.contentType = 'text/plain'\n >>> file.contentType\n 'text/plain'\n\n >>> file.data = 'Foobar'\n >>> file.data\n 'Foobar'\n\n >>> file.data = None\n Traceback (most recent call last):\n ...\n TypeError: Cannot set None data on a file.\n\n\nLet's test large data input:\n\n >>> file = File()\n\nInsert as string:\n\n >>> file.data = 'Foobar'*60000\n >>> file.getSize()\n 360000\n >>> file.data == 'Foobar'*60000\n True\n\nInsert data as FileChunk:\n\n >>> from zope.app.file.file import FileChunk\n >>> fc = FileChunk('Foobar'*4000)\n >>> file.data = fc\n >>> file.getSize()\n 24000\n >>> file.data == 'Foobar'*4000\n True\n\nInsert data from file object:\n\n >>> import cStringIO\n >>> sio = cStringIO.StringIO()\n >>> sio.write('Foobar'*100000)\n >>> sio.seek(0)\n >>> file.data = sio\n >>> file.getSize()\n 600000\n >>> file.data == 'Foobar'*100000\n True\n\n\nLast, but not least, verify the interface:\n\n >>> from zope.interface.verify import verifyClass\n >>> zope.app.file.interfaces.IFile.implementedBy(File)\n True\n >>> verifyClass(zope.app.file.interfaces.IFile, File)\n True\n\n\nTest of Filerepresentation Adapters\n-----------------------------------\n\n >>> from zope.app.file.file import FileReadFile\n >>> file = File()\n >>> content = \"This is some file\\\\ncontent.\"\n >>> file.data = content\n >>> file.contentType = \"text/plain\"\n >>> FileReadFile(file).read() == content\n True\n >>> FileReadFile(file).size() == len(content)\n True\n\n >>> from zope.app.file.file import FileWriteFile\n >>> file = File()\n >>> content = \"This is some file\\\\ncontent.\"\n >>> FileWriteFile(file).write(content)\n >>> file.data == content\n True\n\n\n\nEvolution of Existing Files\n---------------------------\n\nPlease note that the following code is experimental. The code should not be\nused in production without careful testing. Backup your Data.fs and uncomment \nthe following lines in the configure.zcml if you want to replace exiting\nzope.app.file.File instances.\n\n \n\nLet's assume that you have already an existing database with zope.app.file\ncontent types:\n \n >>> from z3c.blobfile import testing\n >>> root = getRootFolder()\n\n >>> root[u'file'] = File('A text file', contentType='text/plain')\n >>> root[u'image'] = Image(testing.zptlogo)\n\nSince the evolve step looks for implementations of IFile we also must\nprovide a way to recognize other implementations than zope.app.file.File and\nImage. Let's add a nonsense implementation as an example:\n\n >>> root[u'custom'] = testing.MyFile()\n \nNote that we cannot assume that these objects exist in isolation. Many of\nthem probably are annotated, indexed, some even may be registered as utility\netc. The evolution step throws the standard events when the objects\nare replaced and it's up the application that this replacement is recognized\naccordingly. If your application has special needs you may subscribe to the\nFileReplacedEvent.\n\nWe will not test all relations to all other objects, since this is largely \napplication dependent. Here we only take the ZopeDublinCore timestamps as \nan example that our evolution step leaves as many things untouched as possible. \n\n >>> from zope.dublincore.interfaces import IZopeDublinCore\n >>> import datetime\n \n >>> IZopeDublinCore(root[u'file']).created = datetime.datetime.utcnow()\n >>> t1 = IZopeDublinCore(root[u'file']).created \n >>> IZopeDublinCore(root[u'file']).title = u'No evolution'\n\nNow we perform the basic evolution steps. Since we expect some warning logs\nwe need \n\n >>> from zope.testing.loggingsupport import InstalledHandler\n >>> import logging\n >>> log_handler = InstalledHandler('z3c.blobfile.generations')\n \n >>> from z3c.blobfile.generations.evolve1 import evolveZopeAppFile\n >>> evolveZopeAppFile(root)\n >>> transaction.commit()\n \n >>> for record in log_handler.records:\n ... print record.getMessage()\n Unknown ...interfaces.IFile implementation z3c.blobfile.testing.MyFile\n\nAfter the evolution step the class types have changed to the z3c.blobfile\nimplementations:\n\n >>> import z3c.blobfile\n >>> isinstance(root[u'file'], z3c.blobfile.file.File)\n True\n >>> isinstance(root[u'image'], z3c.blobfile.image.Image)\n True\n\nOnly the custom implementations remain untouched:\n\n >>> isinstance(root[u'custom'], testing.MyFile)\n True\n \nThe file data remain the same ...\n\n >>> root[u'file'].data\n 'A text file'\n >>> root[u'file'].contentType\n 'text/plain'\n \n >>> root[u'image'].data == testing.zptlogo\n True\n \nand so do the annotations:\n\n >>> IZopeDublinCore(root[u'file']).created == t1\n True\n >>> IZopeDublinCore(root[u'file']).title\n u'No evolution'\n \nEven implementation details like the _data attribute still work:\n\n >>> root[u'file']._data\n 'A text file'\n \n\nCopying\n-------\n\nLet's check that blob files can be copied successfully. This\nfunctionality requires the new \"zope.copy\" package and the\nversion of zope.copypastemove that uses zope.copy (>=3.5.1).\n\n >>> from zope.copy import copy\n >>> file = z3c.blobfile.file.File()\n >>> file.data = u'hello, world'\n >>> image = z3c.blobfile.file.File()\n >>> image.data = 'some image bytes'\n >>> transaction.commit()\n\n >>> file_copy = copy(file)\n >>> file_copy.data == file.data\n True\n\n >>> image_copy = copy(image)\n >>> image_copy.data == image.data\n True\n \n\n=======\nCHANGES\n=======\n\n0.1.5 (2011-02-11)\n------------------\n\n- Put a ceiling (64k) on the number of info bytes read and read those bytes in\n one shot.\n\n- Bug: Correctly detect the dimensions of JPEG images with the dimensions\n in a position greater than IMAGE_INFO_BYTES.\n\n- Made tests compatible with ZODB 3.9.\n\n\n0.1.4 (2009-03-03)\n------------------\n\n- Add copy hook for zope.copy to fix blob file/image copying.\n- Change package's mailing list address to zope-dev at zope.org\n instead of retired zope3-dev.\n\n0.1.3 (2008-10-20)\n------------------\n\n- Bug: Don't get/set image data twice on Image initialization.\n- Cache file size and invalidate it on write access.\n- Download file/image using new openDetached method that provides\n read-only file-like access to the blob, detached from the database\n connection.\n\n0.1.2 (2008-09-11)\n------------------\n\n- Bug: Set i18n domain in \"overrides.zcml\" to avoid warnings.\n- Don't expose Blob implementation details in add/upload forms. Also, \"zope\"\n translation domain has no translations for \"Upload a File (Blob)\", it just\n has \"Upload a File\" translations, so use it.\n\n0.1.1 (2008-09-08)\n------------------\n\n- Bug: Register zope.app.wsgi.fileresult.FileResult as an adapter for BlobFile,\n making optimized file views really work.\n- Bug: Also use optimized file view for z3c.blobfile.image.Image.\n- Bug: Make blob versions of File and Image implement IBlobFile and\n IBlobImage interfaces respectively. This enables z3c.blobfile's views.\n- Bug: Use local ZopeMessageFactory. This fixes import error on Zope 2.10\n\n0.1.0 (2008-02-27)\n------------------\n\n- Initial Release", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://pypi.python.org/pypi/z3c.blobfile", "keywords": "zope3 ZODB blob file image content", "license": "ZPL 2.1", "maintainer": null, "maintainer_email": null, "name": "z3c.blobfile", "package_url": "https://pypi.org/project/z3c.blobfile/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/z3c.blobfile/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://pypi.python.org/pypi/z3c.blobfile" }, "release_url": "https://pypi.org/project/z3c.blobfile/0.1.5/", "requires_dist": null, "requires_python": null, "summary": "File and Image Using Blob Support of ZODB -- Zope 3 Content Components", "version": "0.1.5" }, "last_serial": 801998, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "a85058d69a829674071696590014704d", "sha256": "ee79974f681930dc207076d870f8a1bbba99ce70dd34c145939a42c5a9f5ca65" }, "downloads": -1, "filename": "z3c.blobfile-0.1.0.tar.gz", "has_sig": false, "md5_digest": "a85058d69a829674071696590014704d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19106, "upload_time": "2008-02-27T08:39:57", "url": "https://files.pythonhosted.org/packages/eb/ce/5b02e923cbd78a61bdf4407d8f20d1074a93e8c3b4a63da8c314be32045f/z3c.blobfile-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "f799503ecd0d2e3ff53a32b10c3043dd", "sha256": "73493b9dac6a61ce75ee459510c6695c476d2d62d73fd057d871b1d3b57141dd" }, "downloads": -1, "filename": "z3c.blobfile-0.1.1.tar.gz", "has_sig": false, "md5_digest": "f799503ecd0d2e3ff53a32b10c3043dd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18957, "upload_time": "2008-09-08T11:45:57", "url": "https://files.pythonhosted.org/packages/f8/8f/fded4bd9f1fddeaad968d14b5e4643e2b1e0246ae0563699dde22fa50422/z3c.blobfile-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "dd322fbef2e5ca465c3642dff35fd1b8", "sha256": "611d8e35557cd9a8259267912f3ea332b88a388b76a9931468f0be27e18e5dba" }, "downloads": -1, "filename": "z3c.blobfile-0.1.2.tar.gz", "has_sig": false, "md5_digest": "dd322fbef2e5ca465c3642dff35fd1b8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19083, "upload_time": "2008-09-11T10:19:47", "url": "https://files.pythonhosted.org/packages/31/50/e029545f80749f455044d234280a34e1b380df8c2a2130c9fa7760be5d79/z3c.blobfile-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "8af748137444b0fe1ea1b3d22791a7bf", "sha256": "6a5a9148fe92b071a3b1e7105d748b0e137f8ac61d7d154ee66987ffc90f0131" }, "downloads": -1, "filename": "z3c.blobfile-0.1.3.tar.gz", "has_sig": false, "md5_digest": "8af748137444b0fe1ea1b3d22791a7bf", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19375, "upload_time": "2008-10-20T08:40:16", "url": "https://files.pythonhosted.org/packages/92/47/71c629ee23d6f2d925336abfe8892a542568f4bf620b7f6e4e37597918f9/z3c.blobfile-0.1.3.tar.gz" } ], "0.1.4": [ { "comment_text": "", "digests": { "md5": "fa51b8abd4502d18f65889d0daf58483", "sha256": "9bb3c2843f49489305e404d2b261c99ca7c11bb1a6a407571c31c76d6554a4d7" }, "downloads": -1, "filename": "z3c.blobfile-0.1.4.tar.gz", "has_sig": false, "md5_digest": "fa51b8abd4502d18f65889d0daf58483", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20317, "upload_time": "2009-03-03T17:27:50", "url": "https://files.pythonhosted.org/packages/f5/47/6d312671e5b5b460dc6dd7f3a4108001253a7d2fbb54b7b035124f806280/z3c.blobfile-0.1.4.tar.gz" } ], "0.1.5": [ { "comment_text": "", "digests": { "md5": "2e806640aa2f3b51e4578f35c44f567a", "sha256": "f1695da9de4eaf241a8214c8cf8663d85d1de11b8ea9f552b4398d449ec65353" }, "downloads": -1, "filename": "z3c.blobfile-0.1.5.zip", "has_sig": false, "md5_digest": "2e806640aa2f3b51e4578f35c44f567a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 40925, "upload_time": "2011-02-11T19:30:38", "url": "https://files.pythonhosted.org/packages/8f/44/46d7f7592d42c76be006184af6a7f21fe713d9020a0335e42a11b8a77bb6/z3c.blobfile-0.1.5.zip" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "2e806640aa2f3b51e4578f35c44f567a", "sha256": "f1695da9de4eaf241a8214c8cf8663d85d1de11b8ea9f552b4398d449ec65353" }, "downloads": -1, "filename": "z3c.blobfile-0.1.5.zip", "has_sig": false, "md5_digest": "2e806640aa2f3b51e4578f35c44f567a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 40925, "upload_time": "2011-02-11T19:30:38", "url": "https://files.pythonhosted.org/packages/8f/44/46d7f7592d42c76be006184af6a7f21fe713d9020a0335e42a11b8a77bb6/z3c.blobfile-0.1.5.zip" } ] }