Commit 4eed282c authored by Kirill Smelkov's avatar Kirill Smelkov

go/zodb: Add support for class aliases

Sometimes class name of an object changes, but to support loading
previously-saved objects, the old class name has to be also supported.

For example wendelin.core has ZBlk0 class, but historically used just
"ZBlk" name for it:

https://lab.nexedi.com/nexedi/wendelin.core/blob/v0.12-6-g318efce/bigfile/file_zodb.py#L377

Both class names have to be supported on loading and resolve to to
ZBlk0-typed runtime object.
parent df936d75
......@@ -358,6 +358,38 @@ func RegisterClass(class string, typ, stateType reflect.Type) {
typeTab[typ] = zc
}
// RegisterClassAlias registers alias for a ZODB class.
//
// When ZODB loads an object whose class is alias, it will be handled like
// object with specified ZODB class.
//
// Class aliases are useful for backward compatibility - sometimes class name
// of an object changes, but to support loading previously-saved objects, the
// old class name has to be also supported.
func RegisterClassAlias(alias, class string) {
badf := func(format string, argv ...interface{}) {
msg := fmt.Sprintf(format, argv...)
panic(fmt.Sprintf("zodb: register class alias (%q -> %q): %s", alias, class, msg))
}
if alias == "" {
badf("alias must be not empty")
}
if class == "" {
badf("class must be not empty")
}
if zc, already := classTab[alias]; already {
badf("class %q already registered for type %q", alias, zc.typ)
}
if _, already := classTab[class]; !already {
badf("class %q is not yet registered", class)
}
classTab[alias] = classTab[class]
// don't touch typeTab - this way type -> zclass will always go to
// original class, not alias.
}
// NewPersistent creates new instance of persistent type.
//
// typ must embed Persistent and must be registered with RegisterClass.
......
......@@ -54,6 +54,7 @@ func (o *myObjectState) PySetState(pystate interface{}) error {
func init() {
t := reflect.TypeOf
RegisterClass("t.zodb.MyObject", t(MyObject{}), t(myObjectState{}))
RegisterClassAlias("t.zodb.MyOldObject", "t.zodb.MyObject")
}
func TestPersistent(t *testing.T) {
......@@ -119,7 +120,16 @@ func TestPersistent(t *testing.T) {
}
checkObj(obj, nil, 11, InvalidTid, GHOST, 0, nil)
assert.Equal(zclassOf(obj), "t.zodb.MyObject")
// t.zodb.MyOldObject -> *MyObject
xobj = newGhost("t.zodb.MyOldObject", 12, nil)
obj, ok = xobj.(*MyObject)
if !ok {
t.Fatalf("t.zodb.MyOldObject -> %T; want MyObject", xobj)
}
checkObj(obj, nil, 12, InvalidTid, GHOST, 0, nil)
assert.Equal(zclassOf(obj), "t.zodb.MyObject")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment