{ "info": { "author": "Jazkarta", "author_email": "team@jazkarta.com", "bugtrack_url": null, "classifiers": [ "Framework :: Plone", "Framework :: Zope2", "Intended Audience :: Developers", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "plone.checksum\n==============\n\nOverview\n--------\n\nChecksums for ZODB data\n\nGeneral\n-------\n\nThis package defines a `ChecksumManager` that's used to calculate,\naccess, and write checksums to individual fields of an object. Let's\ncreate an Archetypes `Document` content object:\n\n >>> folder = self.folder\n >>> folder.invokeFactory('Document', 'mydocument', title='My Document')\n 'mydocument'\n >>> doc = folder.mydocument\n\nWe can now request a ChecksumManager for an object like so:\n\n >>> from plone.checksum import IChecksumManager\n >>> manager = IChecksumManager(doc)\n\nThe manager maps field names to `IChecksum` objects:\n\n >>> sorted(manager.keys())\n ['allowDiscussion', 'contributors', 'creation_date', 'creators', 'description', 'effectiveDate', 'excludeFromNav', 'expirationDate', 'id', 'language', ..., 'text', 'title']\n\nWe keep the checksum for our object's title around as `original` for\nthe following tests:\n\n >>> original = str(manager['title'])\n >>> print original\n f796979e29808c04f422574ac403baeb\n\nWe can manually invoke the checksum calculation using the `calculate`\nmethod of checksum objects. The stored and the calculated checksum\nshould certainly be the same at this point:\n\n >>> print manager['title'].calculate()\n f796979e29808c04f422574ac403baeb\n\nChecksums are written (and attached to the object that has the field)\nusing the `update` method:\n\n >>> manager['title'].update('something else')\n >>> print manager['title']\n something else\n\nLet's revert back to the correct checksum by using the\n`update_checksums` method on the checksum manager:\n\n >>> manager.update_checksums()\n >>> print manager['title']\n f796979e29808c04f422574ac403baeb\n\nFinally, we'll change the title and verify that the checksum has\nchanged:\n\n >>> doc.setTitle('something else')\n >>> print manager['title'].calculate()\n 6c7ba9c5a141421e1c03cb9807c97c74\n\nHowever, the stored checksum is still the old value. We need to fix\nthis by firing the modified event again. This time, we won't fire the\nevent ourselves, we'll call `processForm`, which fires the event for\nus:\n\n >>> print manager['title']\n f796979e29808c04f422574ac403baeb\n >>> doc.processForm()\n >>> print manager['title']\n 6c7ba9c5a141421e1c03cb9807c97c74\n \nBy the way, this is equal to:\n\n >>> import md5\n >>> print md5.new('something else').hexdigest()\n 6c7ba9c5a141421e1c03cb9807c97c74\n\nFiles\n-----\n\nLet's create a File content object: After that, we look at the\nchecksum for the `file` field:\n\n >>> from StringIO import StringIO\n >>> folder.invokeFactory('File', 'myfile')\n 'myfile'\n >>> file = folder.myfile\n >>> manager = IChecksumManager(file)\n >>> print manager['file']\n d41d8cd98f00b204e9800998ecf8427e\n\nLet's fill the content's `file` field with some contents:\n\n >>> contents = StringIO('some contents')\n >>> file.setFile(contents)\n >>> print manager['file'].calculate()\n 220c7810f41695d9a87d70b68ccf2aeb\n\nIf we set the file's contents to something else, the checksum changes:\n\n >>> contents = StringIO('something else')\n >>> file.setFile(contents)\n >>> print manager['file'].calculate()\n 6c7ba9c5a141421e1c03cb9807c97c74\n\nThe same should also work for larger files. Note that the contents\nhere are stored in a different structure internally:\n\n >>> contents = StringIO('some contents, ' * 10000)\n >>> file.setFile(contents)\n >>> print manager['file'].calculate()\n 8d43d3687f3684666900db3945712e90\n\nLet's make sure once again that the checksum changes when we set\nanother large file. This time around we'll upload the file using the\n`PUT` method and we'll make sure that the checksum calculation has\nbeen triggered:\n\n >>> from Products.Archetypes.tests.utils import aputrequest\n >>> contents = StringIO('something else, ' * 10000)\n >>> request = aputrequest(contents, 'text/plain')\n >>> request.processInputs()\n >>> ignore = file.PUT(request, request.RESPONSE)\n >>> str(file.getFile()) == contents.getvalue()\n True\n >>> print manager['file']\n 4003a21edc0b8d93bda0ce0c4fa71cfa\n\nThis is again the same as:\n\n >>> print md5.new(contents.getvalue()).hexdigest()\n 4003a21edc0b8d93bda0ce0c4fa71cfa\n\nBlobFile support\n----------------\n\nSome setup:\n\n >>> import md5\n >>> from StringIO import StringIO\n >>> from plone.checksum import IChecksumManager\n\n >>> from Products.BlobFile.Extensions.install import install\n >>> dontcare = install(self.portal)\n\nActual tests:\n\n >>> folder.invokeFactory('BlobFile', 'myblob')\n 'myblob'\n >>> blob = folder.myblob\n >>> manager = IChecksumManager(blob)\n >>> print manager['file']\n n/a\n >>> print manager['file'].calculate()\n d41d8cd98f00b204e9800998ecf8427e\n\nLet's fill the content's `file` field with some contents:\n\n >>> contents = StringIO('some contents, ' * 10000)\n >>> blob.setFile(contents)\n >>> print manager['file'].calculate()\n 8d43d3687f3684666900db3945712e90\n\nIf we set the file's contents to something else, the checksum changes:\n\n >>> contents = StringIO('something else, ' * 10000)\n >>> blob.setFile(contents)\n >>> print manager['file'].calculate()\n 4003a21edc0b8d93bda0ce0c4fa71cfa\n >>> print md5.new(contents.getvalue()).hexdigest()\n 4003a21edc0b8d93bda0ce0c4fa71cfa\n\nUser interface\n--------------\n\nThe `check_all` lists items where the checksum stored in the ZODB\ndiffers with the checksum that's calculated on the fly:\n\n >>> self.loginAsPortalOwner()\n >>> check_all = self.portal.unrestrictedTraverse('checksum__check_all')\n >>> print check_all() # doctest: +ELLIPSIS\n The following items failed the checksum test:\n ...\n\nFor quite a bunch of objects in our newly created portal, the modified\nevent was not fired. Let's use the other view, `update_all` to set\nthe checksum for all objects to the calculated one:\n\n >>> update_all = self.portal.unrestrictedTraverse('checksum__update_all')\n >>> print update_all()\n Calculated and stored checksums of ... items.\n\nNow, `check_all` should give us green light:\n\n >>> print check_all()\n All ... objects verified and OK!\n\nWe can generate small reports using the `print_all` view. Let's say\nwe're interested in the checksums of the `title` fields of all the\nobjects in the portal:\n\n >>> request = self.portal.REQUEST\n >>> print_all = self.portal.unrestrictedTraverse('checksum__print_all')\n >>> request.form['checksum_fields'] = ['title']\n >>> print; print print_all()\n \n ...\n a47176ba668e5ddee74e58c2872659c7 http://nohost/plone/front-page :title\n ...\n\nWe can also format the output like we want it. Available keys are:\n\n >>> output_form = ('%(checksum)s %(url)s %(fieldname)s '\n ... '%(content_type)s %(filename)s')\n >>> request.form['checksum_output'] = output_form\n\nNote that `content_type` is only available for files. And that\n`filename` is currently only available for `OFSBlobFile` values, from\nthe blob_ Product.\n\nThis time we'll create a report with all title fields of all our\n`File` content objects:\n\n >>> request.form['checksum_fields'] = ['title']\n >>> request.form['portal_type'] = 'File'\n >>> print print_all()\n\nOh well, there are no files. Let's fix this. We'll create a fake GIF\nfile:\n\n >>> contents = 'GIF89a xxx'\n >>> self.folder.invokeFactory('File', 'myfile', file=contents)\n 'myfile'\n >>> print print_all()\n d41d8cd98f00b204e9800998ecf8427e http://nohost/plone/Members/test_user_1_/myfile title n/a n/a\n\nWhen we request a report for the 'file' field, we'll get that extra\n`content_type` field in the output:\n\n >>> request.form['checksum_fields'] = ['file']\n >>> print print_all()\n e429b46baca83aa4a713965f5146f31a http://nohost/plone/Members/test_user_1_/myfile file image/gif n/a\n\nIs this what we expect? Yes it is:\n\n >>> import md5\n >>> print md5.new('GIF89a xxx').hexdigest()\n e429b46baca83aa4a713965f5146f31a\n\nIf you wanted a md5sum- compatible report of all `BlobFiles` in your\nportal, you would visit::\n\n http://myportal/checksum__print_all?portal_type=BlobFile&checksum_fields:list=file&checksum_output=%(checksum)s%20%20%(filename)s\n\n\n\n.. _blob: http://www.plope.com/software/blob\n\nCMFEditions support\n-------------------\n\nplone.checksum has CMFEditions support insofar as the query, update\nand print operations will take into account versions of items when\nthey wouldn't show with an ordinary catalog search.\n\nLet's do some general setup:\n\n >>> self.loginAsPortalOwner()\n >>> from plone.checksum import IChecksumManager\n >>> request = self.folder.REQUEST\n >>> repository = self.portal.portal_repository\n\nLet's create a document and create a version of it:\n\n >>> self.folder.invokeFactory('Document', 'mydocument')\n 'mydocument'\n >>> doc = self.folder.mydocument\n >>> doc.setTitle('First version')\n >>> repository.applyVersionControl(doc)\n\nNow we'll modify the document and save the current version.\nAfterwards, we should have two versions:\n\n >>> doc.setTitle('Second version')\n >>> repository.save(doc)\n >>> history = repository.getHistory(doc)\n >>> print history[0].object.Title()\n Second version\n >>> print history[1].object.Title()\n First version\n >>> len(history)\n 2\n\nLet's update all checksums using the `update_all` view method:\n\n >>> update_all = self.portal.unrestrictedTraverse('checksum__update_all')\n >>> print update_all()\n Calculated and stored checksums of ... items.\n\nHowever, `print_all` returns an incorrect checksum for the first version:\n\n >>> print_all = self.portal.unrestrictedTraverse('checksum__print_all')\n >>> request.form['checksum_fields'] = ['title']\n >>> request.form['path'] = '/'.join(doc.getPhysicalPath())\n >>> print print_all()\n cd9dc5fb4185366e3f551f325c572288 http://nohost/plone/Members/test_user_1_/mydocument :title\n d41d8cd98f00b204e9800998ecf8427e http://nohost/plone/Members/test_user_1_/mydocument :title\n\nWhy is that so? It's because we didn't initially give our document a\ntitle, so the generated checksum is for an empty string. `update_all`\ndoesn't touch older versions. If it would, it would have to also store\nolder versions again. Updating the checksum of older versions is\ntherefore not something we are worried about usually.\n\nLet's create another version now. After running `update_all` when the\nthird version is in place, we'll see that the last two versions have a\nchecksum when we do `print_all`. That's because we ran `update_all`\nwhen the second version was the active version. Normally, through the\nweb, every change triggers the modified event, and therefore you don't\nhave to worry about this, it'll just work.\n\n >>> doc.setTitle('Third version')\n >>> repository.save(doc)\n\nBefore we move on, let's make sure that we can retrieve the second\nversion and get its checksum:\n\n >>> second_version = repository.retrieve(doc, 1).object\n >>> print second_version.Title()\n Second version\n >>> print str(IChecksumManager(second_version)['title'])\n cd9dc5fb4185366e3f551f325c572288\n\nNow we update all checksums and print them:\n\n >>> print update_all()\n Calculated and stored checksums of ... items. \n >>> print print_all()\n 26b9d2c5bb8820c1c6de354c9015b2a1 http://nohost/plone/Members/test_user_1_/mydocument :title\n cd9dc5fb4185366e3f551f325c572288 http://nohost/plone/Members/test_user_1_/mydocument :title\n n/a http://nohost/plone/Members/test_user_1_/mydocument :title\n\nIs this what we expect? Yes it is:\n\n >>> import md5\n >>> print md5.new('Third version').hexdigest()\n 26b9d2c5bb8820c1c6de354c9015b2a1\n >>> print md5.new('Second version').hexdigest()\n cd9dc5fb4185366e3f551f325c572288\n\nChangelog\n=========\n\n0.1\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": "http://svn.plone.org/svn/collective/plone.checksum", "keywords": "zodb zope integrity", "license": "GPL", "maintainer": null, "maintainer_email": null, "name": "plone.checksum", "package_url": "https://pypi.org/project/plone.checksum/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/plone.checksum/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://svn.plone.org/svn/collective/plone.checksum" }, "release_url": "https://pypi.org/project/plone.checksum/0.1/", "requires_dist": null, "requires_python": null, "summary": "Checksums for ZODB", "version": "0.1" }, "last_serial": 796385, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "50803e9b2271c6b32c273e672b1e102f", "sha256": "c8af4f43af8dfc1e90f0d817dfca2d30645e4c601fd68ea4f3fbccea8ee9920a" }, "downloads": -1, "filename": "plone.checksum-0.1-py2.4.egg", "has_sig": false, "md5_digest": "50803e9b2271c6b32c273e672b1e102f", "packagetype": "bdist_egg", "python_version": "2.4", "requires_python": null, "size": 23121, "upload_time": "2008-04-01T16:08:23", "url": "https://files.pythonhosted.org/packages/23/16/17c9a9a69a57f14bd51ecd8950a8c11246eed96a8ee188341d0a80835e86/plone.checksum-0.1-py2.4.egg" }, { "comment_text": "", "digests": { "md5": "9a4a38144319bd824c40c335978ee0da", "sha256": "f43c5f822e06b36b7cab44c1cf05753219bb67defb97fb65729b26ff51dafb1f" }, "downloads": -1, "filename": "plone.checksum-0.1.tar.gz", "has_sig": false, "md5_digest": "9a4a38144319bd824c40c335978ee0da", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18660, "upload_time": "2008-04-04T21:32:37", "url": "https://files.pythonhosted.org/packages/d6/20/420349cd969ef769a5640ce46893fbc4a8be97aa60ba6e92c3021ae6b6fb/plone.checksum-0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "50803e9b2271c6b32c273e672b1e102f", "sha256": "c8af4f43af8dfc1e90f0d817dfca2d30645e4c601fd68ea4f3fbccea8ee9920a" }, "downloads": -1, "filename": "plone.checksum-0.1-py2.4.egg", "has_sig": false, "md5_digest": "50803e9b2271c6b32c273e672b1e102f", "packagetype": "bdist_egg", "python_version": "2.4", "requires_python": null, "size": 23121, "upload_time": "2008-04-01T16:08:23", "url": "https://files.pythonhosted.org/packages/23/16/17c9a9a69a57f14bd51ecd8950a8c11246eed96a8ee188341d0a80835e86/plone.checksum-0.1-py2.4.egg" }, { "comment_text": "", "digests": { "md5": "9a4a38144319bd824c40c335978ee0da", "sha256": "f43c5f822e06b36b7cab44c1cf05753219bb67defb97fb65729b26ff51dafb1f" }, "downloads": -1, "filename": "plone.checksum-0.1.tar.gz", "has_sig": false, "md5_digest": "9a4a38144319bd824c40c335978ee0da", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18660, "upload_time": "2008-04-04T21:32:37", "url": "https://files.pythonhosted.org/packages/d6/20/420349cd969ef769a5640ce46893fbc4a8be97aa60ba6e92c3021ae6b6fb/plone.checksum-0.1.tar.gz" } ] }