Commit 656974e2 authored by Kirill Smelkov's avatar Kirill Smelkov Committed by Kamil Kisiel

encoder: Fix class wrt protocol version

- we can use STACK_GLOBAL only if protocol >= 4.
- for earlier protocols we have to use text-based GLOBAL.
parent 95f42543
...@@ -406,7 +406,7 @@ func (e *Encoder) encodeMap(m reflect.Value) error { ...@@ -406,7 +406,7 @@ func (e *Encoder) encodeMap(m reflect.Value) error {
} }
func (e *Encoder) encodeCall(v *Call) error { func (e *Encoder) encodeCall(v *Call) error {
err := e.emitf("%c%s\n%s\n", opGlobal, v.Callable.Module, v.Callable.Name) err := e.encodeClass(&v.Callable)
if err != nil { if err != nil {
return err return err
} }
...@@ -418,11 +418,22 @@ func (e *Encoder) encodeCall(v *Call) error { ...@@ -418,11 +418,22 @@ func (e *Encoder) encodeCall(v *Call) error {
} }
func (e *Encoder) encodeClass(v *Class) error { func (e *Encoder) encodeClass(v *Class) error {
err := e.emitf("%c'%s'\n%c'%s'\n", opString, v.Module, opString, v.Name) // PEP 3154: Protocol 4 forbids use of the GLOBAL opcode and replaces
// it with STACK_GLOBAL.
if e.config.Protocol >= 4 {
err := e.encodeString(v.Module)
if err != nil {
return err
}
err = e.encodeString(v.Name)
if err != nil { if err != nil {
return err return err
} }
return e.emit(opStackGlobal) return e.emit(opStackGlobal)
}
// else use GLOBAL opcode from protocol 0
return e.emitf("%c%s\n%s\n", opGlobal, v.Module, v.Name)
} }
var errP0PersIDStringLineOnly = errors.New(`protocol 0: persistent ID must be string without \n`) var errP0PersIDStringLineOnly = errors.New(`protocol 0: persistent ID must be string without \n`)
......
...@@ -287,10 +287,16 @@ var tests = []TestEntry{ ...@@ -287,10 +287,16 @@ var tests = []TestEntry{
I("(dp0\nS'a'\np1\nS'1'\np2\nsS'b'\np3\nS'2'\np4\ns.")), I("(dp0\nS'a'\np1\nS'1'\np2\nsS'b'\np3\nS'2'\np4\ns.")),
X("foo.bar # global", Class{Module: "foo", Name: "bar"}, X("foo.bar # global", Class{Module: "foo", Name: "bar"},
P0123("cfoo\nbar\n."), // GLOBAL
P4_("\x8c\x03foo\x8c\x03bar\x93."), // SHORT_BINUNICODE + STACK_GLOBAL
I("S'foo'\nS'bar'\n\x93.")), // STRING + STACK_GLOBAL I("S'foo'\nS'bar'\n\x93.")), // STRING + STACK_GLOBAL
X(`foo.bar("bing") # global + reduce`, Call{Callable: Class{Module: "foo", Name: "bar"}, Args: []interface{}{"bing"}}, X(`foo.bar("bing") # global + reduce`, Call{Callable: Class{Module: "foo", Name: "bar"}, Args: []interface{}{"bing"}},
I("cfoo\nbar\nS'bing'\n\x85R.")), // GLOBAL + STRING + TUPLE1 + REDUCE P0("cfoo\nbar\n(S\"bing\"\ntR."), // GLOBAL + MARK + STRING + TUPLE + REDUCE
P1("cfoo\nbar\n(U\x04bingtR."), // GLOBAL + MARK + SHORT_BINSTRING + TUPLE + REDUCE
P2("cfoo\nbar\nU\x04bing\x85R."), // GLOBAL + SHORT_BINSTRING + TUPLE1 + REDUCE
P3("cfoo\nbar\nX\x04\x00\x00\x00bing\x85R."), // GLOBAL + BINUNICODE + TUPLE1 + REDUCE
P4_("\x8c\x03foo\x8c\x03bar\x93\x8c\x04bing\x85R.")), // SHORT_BINUNICODE + STACK_GLOBAL + TUPLE1 + REDUCE
X(`persref("abc")`, Ref{"abc"}, X(`persref("abc")`, Ref{"abc"},
P0("Pabc\n."), // PERSID P0("Pabc\n."), // PERSID
......
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