ZODB的校验和
项目描述
plone.checksum
概述
ZODB数据校验和
通用
此包定义了一个用于计算、访问和将校验和写入对象单个字段的ChecksumManager。让我们创建一个Archetypes Document内容对象
>>> folder = self.folder >>> folder.invokeFactory('Document', 'mydocument', title='My Document') 'mydocument' >>> doc = folder.mydocument
现在我们可以像这样请求一个对象(如)的ChecksumManager
>>> from plone.checksum import IChecksumManager >>> manager = IChecksumManager(doc)
管理器将字段名映射到IChecksum对象
>>> sorted(manager.keys()) ['allowDiscussion', 'contributors', 'creation_date', 'creators', 'description', 'effectiveDate', 'excludeFromNav', 'expirationDate', 'id', 'language', ..., 'text', 'title']
我们将对象标题的校验和保留为original,以便在下面的测试中使用
>>> original = str(manager['title']) >>> print original f796979e29808c04f422574ac403baeb
我们可以使用校验和对象的calculate方法手动调用校验和计算。此时,存储的和计算出的校验和应该肯定是一样的
>>> print manager['title'].calculate() f796979e29808c04f422574ac403baeb
使用update方法写入校验和(并将其附加到具有该字段的对象)
>>> manager['title'].update('something else') >>> print manager['title'] something else
现在让我们使用校验和管理的update_checksums方法恢复到正确的校验和
>>> manager.update_checksums() >>> print manager['title'] f796979e29808c04f422574ac403baeb
最后,我们将更改标题并验证校验和是否已更改
>>> doc.setTitle('something else') >>> print manager['title'].calculate() 6c7ba9c5a141421e1c03cb9807c97c74
然而,存储的校验和仍然是旧值。我们需要通过再次触发修改事件来修复这个问题。这次,我们不会自己触发事件,而是调用 processForm,它会帮我们触发事件
>>> print manager['title'] f796979e29808c04f422574ac403baeb >>> doc.processForm() >>> print manager['title'] 6c7ba9c5a141421e1c03cb9807c97c74
顺便说一下,这等于
>>> import md5 >>> print md5.new('something else').hexdigest() 6c7ba9c5a141421e1c03cb9807c97c74
文件
让我们创建一个文件内容对象:之后,我们查看 file 字段的校验和
>>> from StringIO import StringIO >>> folder.invokeFactory('File', 'myfile') 'myfile' >>> file = folder.myfile >>> manager = IChecksumManager(file) >>> print manager['file'] d41d8cd98f00b204e9800998ecf8427e
让我们用一些内容填充内容对象的 file 字段
>>> contents = StringIO('some contents') >>> file.setFile(contents) >>> print manager['file'].calculate() 220c7810f41695d9a87d70b68ccf2aeb
如果我们将文件的内容设置成其他东西,校验和就会改变
>>> contents = StringIO('something else') >>> file.setFile(contents) >>> print manager['file'].calculate() 6c7ba9c5a141421e1c03cb9807c97c74
同样,这也适用于较大的文件。注意,这里的内部存储结构是不同的
>>> contents = StringIO('some contents, ' * 10000) >>> file.setFile(contents) >>> print manager['file'].calculate() 8d43d3687f3684666900db3945712e90
让我们再次确认,当我们设置另一个大文件时,校验和会改变。这次我们将使用 PUT 方法上传文件,并确保触发了校验和计算
>>> from Products.Archetypes.tests.utils import aputrequest >>> contents = StringIO('something else, ' * 10000) >>> request = aputrequest(contents, 'text/plain') >>> request.processInputs() >>> ignore = file.PUT(request, request.RESPONSE) >>> str(file.getFile()) == contents.getvalue() True >>> print manager['file'] 4003a21edc0b8d93bda0ce0c4fa71cfa
这又与
>>> print md5.new(contents.getvalue()).hexdigest() 4003a21edc0b8d93bda0ce0c4fa71cfa
BlobFile 支持
一些设置
>>> import md5 >>> from StringIO import StringIO >>> from plone.checksum import IChecksumManager>>> from Products.BlobFile.Extensions.install import install >>> dontcare = install(self.portal)
实际测试
>>> folder.invokeFactory('BlobFile', 'myblob') 'myblob' >>> blob = folder.myblob >>> manager = IChecksumManager(blob) >>> print manager['file'] n/a >>> print manager['file'].calculate() d41d8cd98f00b204e9800998ecf8427e
让我们用一些内容填充内容对象的 file 字段
>>> contents = StringIO('some contents, ' * 10000) >>> blob.setFile(contents) >>> print manager['file'].calculate() 8d43d3687f3684666900db3945712e90
如果我们将文件的内容设置成其他东西,校验和就会改变
>>> contents = StringIO('something else, ' * 10000) >>> blob.setFile(contents) >>> print manager['file'].calculate() 4003a21edc0b8d93bda0ce0c4fa71cfa >>> print md5.new(contents.getvalue()).hexdigest() 4003a21edc0b8d93bda0ce0c4fa71cfa
用户界面
check_all 列出了 ZODB 中存储的校验和与即时计算的校验和不同的项目
>>> self.loginAsPortalOwner() >>> check_all = self.portal.unrestrictedTraverse('checksum__check_all') >>> print check_all() # doctest: +ELLIPSIS The following items failed the checksum test: ...
在我们的新创建的门户中,有很多对象没有触发修改事件。让我们使用其他视图 update_all 来将所有对象的校验和设置为计算值
>>> update_all = self.portal.unrestrictedTraverse('checksum__update_all') >>> print update_all() Calculated and stored checksums of ... items.
现在,check_all 应该会给出绿灯
>>> print check_all() All ... objects verified and OK!
我们可以使用 print_all 视图生成小报告。比如说,我们对门户网站中所有对象的 title 字段的校验和感兴趣
>>> request = self.portal.REQUEST >>> print_all = self.portal.unrestrictedTraverse('checksum__print_all') >>> request.form['checksum_fields'] = ['title'] >>> print; print print_all() <BLANKLINE> ... a47176ba668e5ddee74e58c2872659c7 http://nohost/plone/front-page :title ...
我们也可以按我们的需求格式化输出。可用的键有
>>> output_form = ('%(checksum)s %(url)s %(fieldname)s ' ... '%(content_type)s %(filename)s') >>> request.form['checksum_output'] = output_form
请注意,content_type 只适用于文件。而 filename 目前只适用于 OFSBlobFile 值,来自 blob 产品。
这次我们将创建一个包含所有 File 内容对象的标题字段的报告
>>> request.form['checksum_fields'] = ['title'] >>> request.form['portal_type'] = 'File' >>> print print_all()
哦,没有文件。让我们修复这个问题。我们将创建一个假的 GIF 文件
>>> contents = 'GIF89a xxx' >>> self.folder.invokeFactory('File', 'myfile', file=contents) 'myfile' >>> print print_all() d41d8cd98f00b204e9800998ecf8427e http://nohost/plone/Members/test_user_1_/myfile title n/a n/a
当我们请求 'file' 字段的报告时,我们会在输出中获得额外的 content_type 字段
>>> request.form['checksum_fields'] = ['file'] >>> print print_all() e429b46baca83aa4a713965f5146f31a http://nohost/plone/Members/test_user_1_/myfile file image/gif n/a
这是我们期望的吗?是的,这就是
>>> import md5 >>> print md5.new('GIF89a xxx').hexdigest() e429b46baca83aa4a713965f5146f31a
如果您想获取门户网站中所有 BlobFiles 的 md5sum 兼容报告,请访问
http://myportal/checksum__print_all?portal_type=BlobFile&checksum_fields:list=file&checksum_output=%(checksum)s%20%20%(filename)s
CMFEditions 支持
plone.checksum 在查询、更新和打印操作中支持 CMFEditions,因为它们会考虑项目的版本,而这些项目在普通目录搜索中不会显示。
让我们做一些通用设置
>>> self.loginAsPortalOwner() >>> from plone.checksum import IChecksumManager >>> request = self.folder.REQUEST >>> repository = self.portal.portal_repository
让我们创建一个文档,并为其创建一个版本
>>> self.folder.invokeFactory('Document', 'mydocument') 'mydocument' >>> doc = self.folder.mydocument >>> doc.setTitle('First version') >>> repository.applyVersionControl(doc)
现在我们将修改文档并保存当前版本。之后,我们应该有两个版本
>>> doc.setTitle('Second version') >>> repository.save(doc) >>> history = repository.getHistory(doc) >>> print history[0].object.Title() Second version >>> print history[1].object.Title() First version >>> len(history) 2
让我们使用 update_all 视图方法更新所有校验和
>>> update_all = self.portal.unrestrictedTraverse('checksum__update_all') >>> print update_all() Calculated and stored checksums of ... items.
然而,print_all 返回了第一个版本的错误校验和
>>> print_all = self.portal.unrestrictedTraverse('checksum__print_all') >>> request.form['checksum_fields'] = ['title'] >>> request.form['path'] = '/'.join(doc.getPhysicalPath()) >>> print print_all() cd9dc5fb4185366e3f551f325c572288 http://nohost/plone/Members/test_user_1_/mydocument :title d41d8cd98f00b204e9800998ecf8427e http://nohost/plone/Members/test_user_1_/mydocument :title
为什么这样呢?这是因为我们没有一开始就给我们的文档一个标题,所以生成的校验和是空字符串的。update_all 不接触旧版本。如果它要这样做,它就必须再次存储旧版本。因此,通常我们不会担心更新旧版本的校验和。
现在让我们创建另一个版本。当第三个版本到位时,运行 update_all,我们将看到在 print_all 中最后两个版本有校验和。这是因为我们在第二个版本是活动版本时运行了 update_all。通常,通过网站,每个更改都会触发修改事件,因此您不需要担心这个问题,它会正常工作。
>>> doc.setTitle('Third version') >>> repository.save(doc)
在我们继续之前,让我们确保我们可以检索第二个版本并获取其校验和
>>> second_version = repository.retrieve(doc, 1).object >>> print second_version.Title() Second version >>> print str(IChecksumManager(second_version)['title']) cd9dc5fb4185366e3f551f325c572288
现在我们更新所有校验和并打印它们
>>> print update_all() Calculated and stored checksums of ... items. >>> print print_all() 26b9d2c5bb8820c1c6de354c9015b2a1 http://nohost/plone/Members/test_user_1_/mydocument :title cd9dc5fb4185366e3f551f325c572288 http://nohost/plone/Members/test_user_1_/mydocument :title n/a http://nohost/plone/Members/test_user_1_/mydocument :title
这是我们期望的吗?是的,这就是
>>> import md5 >>> print md5.new('Third version').hexdigest() 26b9d2c5bb8820c1c6de354c9015b2a1 >>> print md5.new('Second version').hexdigest() cd9dc5fb4185366e3f551f325c572288
变更日志
0.1
首次公开发布
项目详情
下载文件
下载适用于您平台的文件。如果您不确定选择哪个,请了解有关 安装包 的更多信息。
源代码发行版
构建发行版
plone.checksum-0.1.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | f43c5f822e06b36b7cab44c1cf05753219bb67defb97fb65729b26ff51dafb1f |
|
MD5 | 9a4a38144319bd824c40c335978ee0da |
|
BLAKE2b-256 | d620420349cd969ef769a5640ce46893fbc4a8be97aa60ba6e92c3021ae6b6fb |
plone.checksum-0.1-py2.4.egg 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | c8af4f43af8dfc1e90f0d817dfca2d30645e4c601fd68ea4f3fbccea8ee9920a |
|
MD5 | 50803e9b2271c6b32c273e672b1e102f |
|
BLAKE2b-256 | 231617c9a9a69a57f14bd51ecd8950a8c11246eed96a8ee188341d0a80835e86 |