Skip to content

Fix initialisation of function, staticmethod and classmethod __dict__ #57

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion py/classmethod.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ func (c *ClassMethod) GetDict() StringDict {

// ClassMethodNew
func ClassMethodNew(metatype *Type, args Tuple, kwargs StringDict) (res Object, err error) {
c := &ClassMethod{}
c := &ClassMethod{
Dict: make(StringDict),
}
err = UnpackTuple(args, kwargs, "classmethod", 1, 1, &c.Callable)
if err != nil {
return nil, err
Expand Down
5 changes: 1 addition & 4 deletions py/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ func NewFunction(code *Code, globals StringDict, qualname string) *Function {
Name: code.Name,
Doc: doc,
Module: module,
Dict: make(StringDict),
}
}

Expand Down Expand Up @@ -193,10 +194,6 @@ func init() {
f.Dict = dict
return nil
},
Fdel: func(self Object) error {
self.(*Function).Dict = nil
return nil
},
}
FunctionType.Dict["__name__"] = &Property{
Fget: func(self Object) (Object, error) {
Expand Down
4 changes: 3 additions & 1 deletion py/staticmethod.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ func (c *StaticMethod) GetDict() StringDict {

// StaticMethodNew
func StaticMethodNew(metatype *Type, args Tuple, kwargs StringDict) (res Object, err error) {
c := &StaticMethod{}
c := &StaticMethod{
Dict: make(StringDict),
}
err = UnpackTuple(args, kwargs, "staticmethod", 1, 1, &c.Callable)
if err != nil {
return nil, err
Expand Down
19 changes: 19 additions & 0 deletions py/tests/classmethod.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2019 The go-python Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.

doc="classmethod"

class A:
@classmethod
def fn(cls, p):
assert cls is A
return p+1

a = A()
assert a.fn(1) == 2

a.x = 3
assert a.x == 3

doc="finished"
130 changes: 130 additions & 0 deletions py/tests/function.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Copyright 2019 The go-python Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.

doc="function"

def fn(p):
"docstring"
return p+1

assert fn(1) == 2

# FIXME this doesn't work yet
#assert fn.__doc__ == "docstring"
#fn.__doc__ = "hello"
#assert fn.__doc__ == "hello"

assert str(type(fn)) == "<class 'function'>"

fn.x = 3
assert fn.x == 3

def f2(p):
return p+2

doc="check __code__"
fn.__code__ = f2.__code__
assert fn(1) == 3
try:
fn.__code__ = "bad"
except TypeError:
pass
else:
assert False, "TypeError not raised"

doc="check __defaults__"
def f3(p=2):
return p
assert f3.__defaults__ == (2,)
assert f3() == 2
f3.__defaults__ = (10,)
assert f3() == 10
assert f3.__defaults__ == (10,)
try:
f3.__defaults__ = "bad"
except TypeError:
pass
else:
assert False, "TypeError not raised"
del f3.__defaults__
assert f3.__defaults__ == None or f3.__defaults__ == ()

doc="check __kwdefaults__"
def f4(*, b=2):
return b
assert f4.__kwdefaults__ == {"b":2}
assert f4() == 2
f4.__kwdefaults__ = {"b":10}
assert f4() == 10
assert f4.__kwdefaults__ == {"b":10}
try:
f4.__kwdefaults__ = "bad"
except TypeError:
pass
else:
assert False, "TypeError not raised"
del f4.__kwdefaults__
assert f4.__kwdefaults__ == None or f4.__kwdefaults__ == {}

doc="check __annotations__"
def f5(a: "potato") -> "sausage":
pass
assert f5.__annotations__ == {'a': 'potato', 'return': 'sausage'}
f5.__annotations__ = {'a': 'potato', 'return': 'SAUSAGE'}
assert f5.__annotations__ == {'a': 'potato', 'return': 'SAUSAGE'}
try:
f5.__annotations__ = "bad"
except TypeError:
pass
else:
assert False, "TypeError not raised"
del f5.__annotations__
assert f5.__annotations__ == None or f5.__annotations__ == {}

doc="check __dict__"
def f6():
pass
assert f6.__dict__ == {}
f6.__dict__ = {'a': 'potato'}
assert f6.__dict__ == {'a': 'potato'}
try:
f6.__dict__ = "bad"
except TypeError:
pass
else:
assert False, "TypeError not raised"
try:
del f6.__dict__
except (TypeError, AttributeError):
pass
else:
assert False, "Error not raised"

doc="check __name__"
def f7():
pass
assert f7.__name__ == "f7"
f7.__name__ = "new_name"
assert f7.__name__ == "new_name"
try:
f7.__name__ = 1
except TypeError:
pass
else:
assert False, "TypeError not raised"

doc="check __qualname__"
def f8():
pass
assert f8.__qualname__ == "f8"
f8.__qualname__ = "new_qualname"
assert f8.__qualname__ == "new_qualname"
try:
f8.__qualname__ = 1
except TypeError:
pass
else:
assert False, "TypeError not raised"

doc="finished"
18 changes: 18 additions & 0 deletions py/tests/staticmethod.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2019 The go-python Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.

doc="staticmethod"

class A:
@staticmethod
def fn(p):
return p+1

a = A()
assert a.fn(1) == 2

a.x = 3
assert a.x == 3

doc="finished"