{ "info": { "author": "Martijn Faassen, Infrae", "author_email": "faassen@startifact.com", "bugtrack_url": null, "classifiers": [ "Framework :: Zope3", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "hurry.file fields\n=================\n\nThe file widget is built on top of the HurryFile object:\n\n >>> from hurry.file import HurryFile\n >>> file = HurryFile('foo.txt', 'mydata')\n >>> file.filename\n 'foo.txt'\n >>> file.data\n 'mydata'\n >>> file.size\n 6\n >>> f = file.file\n >>> f.read()\n 'mydata'\n\nHurryFile objects are equal if data and filename of two of them match:\n\n >>> file1 = HurryFile('foo.txt', 'mydata')\n >>> file2 = HurryFile('foo.txt', 'mydata')\n >>> file3 = HurryFile('bar.txt', 'otherdata')\n >>> file1 == file2\n True\n\n >>> file1 != file2\n False\n\n >>> file1 == file3\n False\n\n >>> file1 != file3\n True\n\nWe can also create HurryFile objects from file-like objects:\n\n >>> from StringIO import StringIO\n >>> from zope import component\n >>> from hurry.file.interfaces import IFileRetrieval\n >>> fileretrieval = component.getUtility(IFileRetrieval)\n >>> file = fileretrieval.createFile('bar.txt', StringIO('test data'))\n >>> file.filename\n 'bar.txt'\n >>> file.size\n 9\n >>> file.data\n 'test data'\n >>> f = file.file\n >>> f.read()\n 'test data'\n\nThis does exactly the same, but may be easier to use:\n\n >>> from hurry.file import createHurryFile\n >>> file = createHurryFile('test2.txt', StringIO('another test file'))\n >>> file.filename\n 'test2.txt'\n >>> file.size\n 17\n\nThe HurryFile object normally stores the file data using ZODB\npersistence. Files can however also be stored by tramline. If\ntramline is installed in Apache, the Tramline takes care of generating\nids for files and storing the file on the filesystem directly. The ids\nare then passed as file data to be stored in the ZODB.\n\nLet's first enable tramline.\n\nThe tramline directory structure is a directory with two subdirectories,\none called 'repository' and the other called 'upload':\n\n >>> import tempfile, os\n >>> dirpath = tempfile.mkdtemp()\n >>> repositorypath = os.path.join(dirpath, 'repository')\n >>> uploadpath = os.path.join(dirpath, 'upload')\n >>> os.mkdir(repositorypath)\n >>> os.mkdir(uploadpath)\n\nWe create a TramlineFileRetrieval object knowing about this directory,\nand register it as a utility:\n\n >>> from hurry.file.file import TramlineFileRetrievalBase\n >>> class TramlineFileRetrieval(TramlineFileRetrievalBase):\n ... def getTramlinePath(self):\n ... return dirpath\n >>> retrieval = TramlineFileRetrieval()\n >>> component.provideUtility(retrieval, IFileRetrieval)\n\nNow let's store a file the way tramline would during upload:\n\n >>> f = open(os.path.join(repositorypath, '1'), 'wb')\n >>> f.write('test data')\n >>> f.close()\n\nThe file with underlying name '1' (the data stored in the ZODB will be\njust '1') will now be created:\n\n >>> file = HurryFile('foo.txt', '1')\n\nThe data is now '1', referring to the real file:\n\n >>> file.data\n '1'\n\nRetrieving the file results in the real file:\n\n >>> f = file.file\n >>> f.read()\n 'test data'\n\nWe can also retrieve its size:\n\n >>> file.size\n 9L\n\nIt should be possible to create Hurry File objects that are stored in\nthe directory structure directly:\n\n >>> file = retrieval.createFile('test.txt', StringIO('my test data'))\n >>> file.filename\n 'test.txt'\n\nWe get an id for the data now:\n\n >>> file.data != 'my test data'\n True\n\nAnd we can retrieve the file itself:\n\n >>> f = file.file\n >>> f.read()\n 'my test data'\n >>> file.size\n 12L\n\nNow let's disable tramline in our utility:\n\n >>> class TramlineFileRetrieval(TramlineFileRetrievalBase):\n ... def getTramlinePath(self):\n ... return dirpath\n ... def isTramlineEnabled(self):\n ... return False\n >>> component.provideUtility(TramlineFileRetrieval(), IFileRetrieval)\n\nWe expect the same behavior as when tramline is not installed:\n\n >>> file = HurryFile('foo.txt', 'data')\n >>> f = file.file\n >>> f.read()\n 'data'\n >>> file.size\n 4\n\nClean up:\n\n >>> import shutil\n >>> shutil.rmtree(dirpath)\n\nhurry.file widgets\n==================\n\nThis is an infrastructure to create a file widget that behaves as much\nas possible like a normal text widget in formlib. Normally a file\nwidget loses its file data when a form is re-presented for reasons of\nfailing form validation. A ``hurry.file`` widget retains the file, for\nexample by storing it in a session.\n\nIn order to do this, we have a special way to store file data along with\nits filename::\n\n >>> from hurry.file import HurryFile\n >>> some_file = HurryFile('foo.txt', 'the contents')\n >>> some_file.filename\n 'foo.txt'\n >>> some_file.data\n 'the contents'\n\nWe can provide a download widget. In this case, there's nothing\nto download::\n\n >>> from hurry.file.browser import DownloadWidget\n >>> from hurry.file.schema import File\n >>> from zope.publisher.browser import TestRequest\n >>> field = File(__name__='foo', title=u'Foo')\n >>> field = field.bind(None)\n >>> request = TestRequest()\n >>> widget = DownloadWidget(field, request)\n >>> widget()\n u'
Download not available
'\n \nEven if there were data in the request, there'd be nothing to download::\n\n >>> from zope.publisher.browser import FileUpload\n >>> request = TestRequest(form={'field.foo': FileUpload(some_file)})\n >>> widget = DownloadWidget(field, request)\n >>> widget()\n u'
Download not available
'\n\nNow set a value::\n\n >>> widget.setRenderedValue(some_file)\n >>> widget()\n u'foo.txt'\n\nNow on to an edit widget. First the case in an add form with no\ndata already available, and no data in request::\n\n >>> from hurry.file.browser import EncodingFileWidget\n >>> field = File(__name__='foo', title=u'Foo', required=False)\n >>> field = field.bind(None)\n >>> request = TestRequest()\n >>> widget = EncodingFileWidget(field, request)\n \n >>> def normalize(s):\n ... return '\\n '.join(filter(None, s.split(' ')))\n\n >>> print normalize(widget())\n \n\nNow let's try a situation where data is available in the request, but\nit's an empty string for the file::\n\n >>> request = TestRequest(form={'field.foo': u''})\n >>> widget = EncodingFileWidget(field, request)\n \n >>> def normalize(s):\n ... return '\\n '.join(filter(None, s.split(' ')))\n\n >>> print normalize(widget())\n \n\nNow let's render again when there's already available data. What should show\nup is an extra, hidden field which contains the file_id::\n\n >>> widget.setRenderedValue(some_file)\n >>> print normalize(widget())\n \n (foo.txt)\n\nNow let's render again, this time with file data available in the request\ninstead. The same should happen::\n\n >>> request = TestRequest(form={'field.foo': FileUpload(some_file)})\n >>> widget = EncodingFileWidget(field, request)\n >>> print normalize(widget())\n \n (foo.txt)\n\nNow let's render again, this time not with file data available in the\nrequest, but an id. Again, we should see the same::\n\n >>> request = TestRequest(form={'field.foo.file_id': \n ... 'Zm9vLnR4dAp0aGUgY29udGVudHM='})\n >>> widget = EncodingFileWidget(field, request)\n >>> print normalize(widget())\n \n (foo.txt)\n\nIf there is both file data and an id, something else happens. First, let's\nprepare some new file::\n\n >>> another_file = HurryFile('bar.txt', 'bar contents')\n\nWe happen to know, due to the implementation of EncodingFileWidget,\nthat the file_id is going to be \"YmFyLnR4dApiYXIgY29udGVudHM=\". Let's\nmake a request with the original id, but a new file upload::\n\n >>> request = TestRequest(form={'field.foo': FileUpload(another_file),\n ... 'field.foo.file_id': \n ... 'Zm9vLnR4dAp0aGUgY29udGVudHM='})\n\nWe expect the new file to be the one that's uploaded::\n\n >>> widget = EncodingFileWidget(field, request)\n >>> print normalize(widget())\n \n (bar.txt)\n\nhurry.file changes\n==================\n\n1.2.1 (2011-08-09)\n------------------\n\n* Fix buggy inequality comparison of HurryFiles.\n\n1.2 (2009-03-11)\n----------------\n\n* Add a 'size' attribute that knows the size of the file in bytes (no\n matter whether it's stored using tramline or in the ZODB).\n\n1.1 (2008-08-07)\n----------------\n\n* Add in a buildout.cfg that installs the test runner.\n\n* List dependencies in setup.py.\n\n* Rely on zope.session instead of zope.app.session to stop deprecation\n warnings.\n\n* Add long description in setup.py based on README.txt and file.txt\n doctests, and CHANGES.txt.\n\n1.0 (2006-10-25)\n----------------\n\n* Support for Tramline (fast file uploads/downloads) through\n IFileRetrieval. By default, nothing changes.\n\n If a subclass of TramlineFileRetrievalBase is registered as a\n IFileRetrieval utility, hurry.file becomes Tramline aware. If files\n are created manually, they can be created through the\n createHurryFile function, or the 'createFile' method of the\n IFileRetrieval service. This will take care of storing the file in\n the right place.\n\n Tramline can be found here: http://codespeak.net/svn/rr/tramline/trunk\n\n0.9.3 (2006-10-23)\n------------------\n\n* Send tramline_ok header back when redisplaying widget, in case we're\n working with tramline.\n\n0.9.2 (2006-09-28)\n------------------\n\n* Zope 3.3 has a change in the way it deals with file name encoding\n which broke hurry.file. This includes a workaround.\n\n0.9.1 (2006-09-22)\n------------------\n\n* first cheeseshop release.\n\n0.9 (2006-06-15)\n----------------\n\n* separation from general hurry package into hurry.file\n\n* eggification\n\n0.8 (2006-05-01)\n----------------\n\nInitial public release.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "UNKNOWN", "keywords": "zope zope3", "license": "ZPL 2.1", "maintainer": null, "maintainer_email": null, "name": "hurry.file", "package_url": "https://pypi.org/project/hurry.file/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/hurry.file/", "project_urls": { "Download": "UNKNOWN", "Homepage": "UNKNOWN" }, "release_url": "https://pypi.org/project/hurry.file/1.2.1/", "requires_dist": null, "requires_python": null, "summary": "hurry.file is an advanced Zope 3 file widget which tries its best to behave\nlike other widgets, even when the form is redisplayed due to a validation\nerror. It also has built-in support for fast Apache-based file uploads\nand downloads through Tramline.", "version": "1.2.1" }, "last_serial": 793117, "releases": { "0.9.1": [ { "comment_text": "", "digests": { "md5": "f30fde3b1bf34974053fce5ccbad549e", "sha256": "3ae7afb7fcd88c01745e2577f16811ae228e767f0ecded75c0131bfc78ae27fe" }, "downloads": -1, "filename": "hurry.file-0.9.1-py2.4.egg", "has_sig": false, "md5_digest": "f30fde3b1bf34974053fce5ccbad549e", "packagetype": "bdist_egg", "python_version": "2.4", "requires_python": null, "size": 13460, "upload_time": "2006-09-22T16:44:32", "url": "https://files.pythonhosted.org/packages/f5/59/0ce32227a9cab5401d83e42538e294a05685b651fa7b2315f27caaf6dc0d/hurry.file-0.9.1-py2.4.egg" }, { "comment_text": "", "digests": { "md5": "de7b16713a57d99dd12fb05f18d43272", "sha256": "6d5a90a64c3004d222b6055ec0b90b412425f73f545d8967744a6f91b29f063f" }, "downloads": -1, "filename": "hurry.file-0.9.1.tar.gz", "has_sig": false, "md5_digest": "de7b16713a57d99dd12fb05f18d43272", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6341, "upload_time": "2006-09-22T16:43:58", "url": "https://files.pythonhosted.org/packages/27/28/25416ca63228c47a6c62883648be9f3507463cbde124d7670b51fe99d176/hurry.file-0.9.1.tar.gz" } ], "0.9.2": [ { "comment_text": "", "digests": { "md5": "ffa3640b8ae890373b8f29aa741b4edb", "sha256": "2a442d064ba22120f7d820cf376484be6346f5a439e7dd1fd0e29179f46f1c77" }, "downloads": -1, "filename": "hurry.file-0.9.2-py2.4.egg", "has_sig": false, "md5_digest": "ffa3640b8ae890373b8f29aa741b4edb", "packagetype": "bdist_egg", "python_version": "2.4", "requires_python": null, "size": 13490, "upload_time": "2006-09-28T16:35:39", "url": "https://files.pythonhosted.org/packages/e0/36/38285cc71d11c382845c10d57cd8a99bd5fdaa4a310a6c0ddae0aa978d0e/hurry.file-0.9.2-py2.4.egg" }, { "comment_text": "", "digests": { "md5": "41c3924b56747764f8ad17e814dcdaa4", "sha256": "389665957c167f94f56975f1ada39c6dd25c41762c80010fa649b88789e59a96" }, "downloads": -1, "filename": "hurry.file-0.9.2.tar.gz", "has_sig": false, "md5_digest": "41c3924b56747764f8ad17e814dcdaa4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6453, "upload_time": "2006-09-28T16:35:32", "url": "https://files.pythonhosted.org/packages/1d/99/cc1ca65f1b64181ad147798793eebdbb6f9ea64ea5c74c8bbf960d052d29/hurry.file-0.9.2.tar.gz" } ], "0.9.3": [ { "comment_text": "", "digests": { "md5": "27190a0cb2178fcc22356e1fffa4bb79", "sha256": "709845e6c8c2dd1ecdf453fa1743f275059d104b3678a2f1aa46c625164f9125" }, "downloads": -1, "filename": "hurry.file-0.9.3-py2.4.egg", "has_sig": false, "md5_digest": "27190a0cb2178fcc22356e1fffa4bb79", "packagetype": "bdist_egg", "python_version": "2.4", "requires_python": null, "size": 13595, "upload_time": "2006-10-23T16:01:11", "url": "https://files.pythonhosted.org/packages/15/d4/7d552066d72f3ca383fd11796fa2acf02ee202504af92563b9be6fcdcd80/hurry.file-0.9.3-py2.4.egg" }, { "comment_text": "", "digests": { "md5": "4e8bd627f43f1df4744d6ee7c0e0974a", "sha256": "c351cef9c6c1df5c42f12816e2170ddf9bcd6b92de066e1eadb369b1b21478ee" }, "downloads": -1, "filename": "hurry.file-0.9.3.tar.gz", "has_sig": false, "md5_digest": "4e8bd627f43f1df4744d6ee7c0e0974a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6543, "upload_time": "2006-10-23T16:01:06", "url": "https://files.pythonhosted.org/packages/af/94/dd226ef3967a5b16d3d0da624ac34281291a0ef6ee2b40a9b61328146694/hurry.file-0.9.3.tar.gz" } ], "1.0": [ { "comment_text": "", "digests": { "md5": "dd8b6ce8e74f4e386ec60929d64ed6e5", "sha256": "45c151de848054b87b80a0063c628fb75ef895b7e8214e001780c796b1a026fd" }, "downloads": -1, "filename": "hurry.file-1.0-py2.4.egg", "has_sig": false, "md5_digest": "dd8b6ce8e74f4e386ec60929d64ed6e5", "packagetype": "bdist_egg", "python_version": "2.4", "requires_python": null, "size": 18244, "upload_time": "2006-10-25T09:11:49", "url": "https://files.pythonhosted.org/packages/f0/18/f2ebf52de3e6b5c2f49f6546e8b068315084a9989695a352206d0a9c9a74/hurry.file-1.0-py2.4.egg" }, { "comment_text": "", "digests": { "md5": "c4047e63ddad367eb35a028009a17209", "sha256": "3ea8bdcab153c04ba698caded39085022b72d334bfc0b83bdba6d2e7568c14fc" }, "downloads": -1, "filename": "hurry.file-1.0.tar.gz", "has_sig": false, "md5_digest": "c4047e63ddad367eb35a028009a17209", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8523, "upload_time": "2006-10-25T09:11:37", "url": "https://files.pythonhosted.org/packages/41/4d/4f64a863cb40edc7bbdfe19a4017d2d67b3babc4dc03004850507d050fcc/hurry.file-1.0.tar.gz" } ], "1.1": [ { "comment_text": "", "digests": { "md5": "f7c4bac7c7147119739037e7b5aff37c", "sha256": "72e380abd2283da63853b72502d0b57fe9b24ed05de39bc82fddf75532072155" }, "downloads": -1, "filename": "hurry.file-1.1.tar.gz", "has_sig": false, "md5_digest": "f7c4bac7c7147119739037e7b5aff37c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11319, "upload_time": "2008-08-07T17:04:50", "url": "https://files.pythonhosted.org/packages/26/ae/d476376a8bc1953005b5fc59f877aa095c4e5843e1c6b676f16de304cbe7/hurry.file-1.1.tar.gz" } ], "1.2": [ { "comment_text": "", "digests": { "md5": "95a7801e01a1c45d36f8765563981e8f", "sha256": "6c5f683e0ec9ce21ea8332093e9e972589684a6b794877159653d1670d3fa2ab" }, "downloads": -1, "filename": "hurry.file-1.2.tar.gz", "has_sig": false, "md5_digest": "95a7801e01a1c45d36f8765563981e8f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14139, "upload_time": "2009-03-11T23:34:13", "url": "https://files.pythonhosted.org/packages/ca/48/ed9f9a4fe5f375fb478f2c33cfe5d363f0dce15288bc0c5271f43335b34c/hurry.file-1.2.tar.gz" } ], "1.2.1": [ { "comment_text": "", "digests": { "md5": "101a9500fecbef8bb62d1b6eee49aeca", "sha256": "e191880e5aacd14c36c59ec6a7303d327bf81fad2b779c25953410cbf58bbfeb" }, "downloads": -1, "filename": "hurry.file-1.2.1.tar.gz", "has_sig": false, "md5_digest": "101a9500fecbef8bb62d1b6eee49aeca", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15133, "upload_time": "2011-08-09T16:20:21", "url": "https://files.pythonhosted.org/packages/ed/73/dacd3813bebada01455ca8cab10c91878135e53cdefba790d70a5462a49e/hurry.file-1.2.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "101a9500fecbef8bb62d1b6eee49aeca", "sha256": "e191880e5aacd14c36c59ec6a7303d327bf81fad2b779c25953410cbf58bbfeb" }, "downloads": -1, "filename": "hurry.file-1.2.1.tar.gz", "has_sig": false, "md5_digest": "101a9500fecbef8bb62d1b6eee49aeca", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15133, "upload_time": "2011-08-09T16:20:21", "url": "https://files.pythonhosted.org/packages/ed/73/dacd3813bebada01455ca8cab10c91878135e53cdefba790d70a5462a49e/hurry.file-1.2.1.tar.gz" } ] }