Commit 0af12a50 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 3f3478c1
...@@ -23,7 +23,6 @@ package zodb ...@@ -23,7 +23,6 @@ package zodb
import ( import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"errors"
"fmt" "fmt"
"lab.nexedi.com/kirr/go123/xerr" "lab.nexedi.com/kirr/go123/xerr"
...@@ -52,7 +51,7 @@ func (d PyData) ClassName() string { ...@@ -52,7 +51,7 @@ func (d PyData) ClassName() string {
return "?.?" return "?.?"
} }
klass, err := normPyClass(xklass) klass, err := xpyclass(xklass)
if err != nil { if err != nil {
return "?.?" return "?.?"
} }
...@@ -78,7 +77,7 @@ func (d PyData) decode(jar *Connection) (pyclass pickle.Class, pystate interface ...@@ -78,7 +77,7 @@ func (d PyData) decode(jar *Connection) (pyclass pickle.Class, pystate interface
return pickle.Class{}, nil, fmt.Errorf("class description: %s", err) return pickle.Class{}, nil, fmt.Errorf("class description: %s", err)
} }
klass, err := normPyClass(xklass) klass, err := xpyclass(xklass)
if err != nil { if err != nil {
return pickle.Class{}, nil, fmt.Errorf("class description: %s", err) return pickle.Class{}, nil, fmt.Errorf("class description: %s", err)
} }
...@@ -110,12 +109,12 @@ func (jar *Connection) loadref(ref pickle.Ref) (_ interface{}, err error) { ...@@ -110,12 +109,12 @@ func (jar *Connection) loadref(ref pickle.Ref) (_ interface{}, err error) {
oid, err := xoid(t[0]) oid, err := xoid(t[0])
if err != nil { if err != nil {
return nil, err // XXX err ctx return nil, err
} }
pyclass, err := normPyClass(t[1]) pyclass, err := xpyclass(t[1])
if err != nil { if err != nil {
return nil, err // XXX err ctx return nil, err
} }
class := pyclassPath(pyclass) class := pyclassPath(pyclass)
...@@ -125,32 +124,34 @@ func (jar *Connection) loadref(ref pickle.Ref) (_ interface{}, err error) { ...@@ -125,32 +124,34 @@ func (jar *Connection) loadref(ref pickle.Ref) (_ interface{}, err error) {
var errInvalidPyClass = errors.New("invalid py class description") // xpyclass verifies and extracts py class from unpickled value.
//
// normPyClass normalizes py class that has just been decoded from a serialized // it normalizes py class that has just been decoded from a serialized ZODB
// ZODB object or reference. // object or reference.
func normPyClass(xklass interface{}) (pickle.Class, error) { //
// class description: // class description:
// //
// - type(obj), or // - type(obj), or
// - (xklass, newargs|None) ; xklass = type(obj) | (modname, classname) // - (xklass, newargs|None) ; xklass = type(obj) | (modname, classname)
func xpyclass(xklass interface{}) (_ pickle.Class, err error) {
defer xerr.Context(&err, "class")
if t, ok := xklass.(pickle.Tuple); ok { if t, ok := xklass.(pickle.Tuple); ok {
// t = (xklass, newargs|None) // t = (xklass, newargs|None)
if len(t) != 2 { if len(t) != 2 {
return pickle.Class{}, errInvalidPyClass return pickle.Class{}, fmt.Errorf("top: expect [2](); got [%d]()", len(t))
} }
// XXX newargs is ignored (zodb/py uses it only for persistent classes) // XXX newargs is ignored (zodb/py uses it only for persistent classes)
xklass = t[0] xklass = t[0]
if t, ok := xklass.(pickle.Tuple); ok { if t, ok := xklass.(pickle.Tuple); ok {
// t = (modname, classname) // t = (modname, classname)
if len(t) != 2 { if len(t) != 2 {
return pickle.Class{}, errInvalidPyClass return pickle.Class{}, fmt.Errorf("xklass: expect [2](); got [%d]()", len(t))
} }
modname, ok1 := t[0].(string) modname, ok1 := t[0].(string)
classname, ok2 := t[1].(string) classname, ok2 := t[1].(string)
if !(ok1 && ok2) { if !(ok1 && ok2) {
return pickle.Class{}, errInvalidPyClass return pickle.Class{}, fmt.Errorf("xklass: expect (str, str); got (%T, %T)", t[0], t[1])
} }
return pickle.Class{Module: modname, Name: classname}, nil return pickle.Class{Module: modname, Name: classname}, nil
...@@ -162,28 +163,29 @@ func normPyClass(xklass interface{}) (pickle.Class, error) { ...@@ -162,28 +163,29 @@ func normPyClass(xklass interface{}) (pickle.Class, error) {
return klass, nil return klass, nil
} }
return pickle.Class{}, errInvalidPyClass return pickle.Class{}, fmt.Errorf("expect type; got %T", xklass)
}
// pyclassPath returns full path for a python class.
//
// for example class "ABC" in module "wendelin.lib" has its full path as "wendelin.lib.ABC".
func pyclassPath(pyclass pickle.Class) string {
return pyclass.Module + "." + pyclass.Name
} }
// xoid verifies and extracts oid from unpickled value. // xoid verifies and extracts oid from unpickled value.
// //
// XXX +zobdpickle.binary support // TODO +zobdpickle.binary support
// XXX -> shared place func xoid(x interface{}) (_ Oid, err error) {
func xoid(x interface{}) (Oid, error) { defer xerr.Context(&err, "oid")
s, ok := x.(string) s, ok := x.(string)
if !ok { if !ok {
return InvalidOid, fmt.Errorf("xoid: expect str; got %T", x) return InvalidOid, fmt.Errorf("expect str; got %T", x)
} }
if len(s) != 8 { if len(s) != 8 {
return InvalidOid, fmt.Errorf("xoid: expect [8]str; got [%d]str", len(s)) return InvalidOid, fmt.Errorf("expect [8]str; got [%d]str", len(s))
} }
return Oid(binary.BigEndian.Uint64([]byte(s))), nil return Oid(binary.BigEndian.Uint64([]byte(s))), nil
} }
// pyclassPath returns full path for a python class.
//
// for example class "ABC" in module "wendelin.lib" has its full path as "wendelin.lib.ABC".
func pyclassPath(pyclass pickle.Class) string {
return pyclass.Module + "." + pyclass.Name
}
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