Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
A Zope command line script to delete content with missing BLOB in Plone
A Zope command line script to delete content with missing BLOB in Plone, causing
POSKeyErrors when content is being accessed or during portal_catalog rebuild.
Tested on Plone 4.1 + Dexterity 1.1.
Also see:
# Zope imports
from ZODB.POSException import POSKeyError
from zope.component import getMultiAdapter
from zope.component import queryUtility
from Products.CMFCore.interfaces import IPropertiesTool
from Products.CMFCore.interfaces import IFolderish, ISiteRoot
# Plone imports
from five import grok
from Products.Archetypes.Field import FileField
from Products.Archetypes.interfaces import IBaseContent
from plone.namedfile.interfaces import INamedFile
from plone.dexterity.content import DexterityContent
def check_at_blobs(context):
""" Archetypes content checker.
Return True if purge needed
if IBaseContent.providedBy(context):
schema = context.Schema()
for field in schema.fields():
id = field.getName()
if isinstance(field, FileField):
except POSKeyError:
print "Found damaged AT FileField %s on %s" % (id, context.absolute_url())
return True
return False
def check_dexterity_blobs(context):
""" Check Dexterity content for damaged blob fields
Return True if purge needed
# Assume dexterity contennt inherits from Item
if isinstance(context, DexterityContent):
# Iterate through all Python object attributes
# XXX: Might be smarter to use zope.schema introspection here?
for key, value in context.__dict__.items():
# Ignore non-contentish attributes to speed up us a bit
if not key.startswith("_"):
if INamedFile.providedBy(value):
except POSKeyError:
print "Found damaged Dexterity %s on %s" % (key, context.absolute_url())
return True
return False
def fix_blobs(context):
Iterate through the object variables and see if they are blob fields
and if the field loading fails then poof
if check_at_blobs(context) or check_dexterity_blobs(context):
print "Bad blobs found on %s" % context.absolute_url() + " -> deleting"
parent = context.aq_parent
def recurse(tree):
""" Walk through all the content on a Plone site """
for id, child in tree.contentItems():
if IFolderish.providedBy(child):
class FixBlobs(grok.CodeView):
A management view to clean up content with damaged BLOB files
You can call this view by
1) Starting Plone in debug mode (console output available)
2) Visit URL
def disable_integrity_check(self):
""" Content HTML may have references to this broken image - we cannot fix that HTML
but link integriry check will yell if we try to delete the bad image. "
ptool = queryUtility(IPropertiesTool)
props = getattr(ptool, 'site_properties', None)
self.old_check = props.getProperty('enable_link_integrity_checks', False)
props.enable_link_integrity_checks = False
def enable_integrity_check(self):
""" """
ptool = queryUtility(IPropertiesTool)
props = getattr(ptool, 'site_properties', None)
props.enable_link_integrity_checks = self.old_check
def render(self):
#plone = getMultiAdapter((self.context, self.request), name="plone_portal_state")
print "Checking blobs"
portal = self.context
print "All done"
return "OK - check console for status messages"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment