Skip to content

Instantly share code, notes, and snippets.

@buchi
Created March 2, 2018 13:41
Show Gist options
  • Save buchi/f6484cd8f42194903271efda967aca8b to your computer and use it in GitHub Desktop.
Save buchi/f6484cd8f42194903271efda967aca8b to your computer and use it in GitHub Desktop.
ZODB: find oids of objects referencing a specific oid
from ZODB.serialize import referencesf
from ZODB.FileStorage import FileStorage
def build_refmap(filename):
"""Build a refmap from a filestorage. Look in every record of every
transaction. Build a dict of oid -> list(referenced oids)
"""
refmap = {}
fs = FileStorage(filename, read_only=1)
fsi = fs.iterator()
for txn in fsi:
for rec in txn:
pickle, revid = fs.load(rec.oid, rec.version)
refs = referencesf(pickle)
refmap[rec.oid] = refs
return refmap
def backrefs(target, refmap):
"""Return a list of oids in the refmap who reference target.
"""
oidlist = []
for oid, refs in refmap.iteritems():
if target in refs:
oidlist.append(oid)
return oidlist
def obj_path(target, refmap):
"""For a target oid find the path of objects that refer to it.
break if we reach no more references or find a cycle
"""
path = [target]
additionals = []
while True:
target = path[-1:].pop()
brefs = backrefs(target, refmap)
if not brefs:
break
bref = brefs[0]
if bref in path:
print 'cyclic', bref
break
if len(brefs) == 1:
path.append(bref)
print bref
continue
additionals.append((target, brefs[1:]))
print bref, brefs[1:]
path.append(bref)
return (path, additionals)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment