Commit cd0345d9 authored by YOU's avatar YOU Committed by Dylan Trotter

Add builtin delattr (#202)

parent 947f6ad4
......@@ -303,6 +303,13 @@ func builtinCmp(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
return Compare(f, args[0], args[1])
}
func builtinDelAttr(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
if raised := checkFunctionArgs(f, "delattr", args, ObjectType, StrType); raised != nil {
return nil, raised
}
return None, DelAttr(f, args[0], toStrUnsafe(args[1]))
}
func builtinDir(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
// TODO: Support __dir__.
if raised := checkFunctionArgs(f, "dir", args, ObjectType); raised != nil {
......@@ -646,6 +653,7 @@ func init() {
"callable": newBuiltinFunction("callable", builtinCallable).ToObject(),
"chr": newBuiltinFunction("chr", builtinChr).ToObject(),
"cmp": newBuiltinFunction("cmp", builtinCmp).ToObject(),
"delattr": newBuiltinFunction("delattr", builtinDelAttr).ToObject(),
"dir": newBuiltinFunction("dir", builtinDir).ToObject(),
"False": False.ToObject(),
"getattr": newBuiltinFunction("getattr", builtinGetAttr).ToObject(),
......
......@@ -23,6 +23,37 @@ import (
"testing"
)
func TestBuiltinDelAttr(t *testing.T) {
f := NewRootFrame()
delattr := mustNotRaise(Builtins.GetItemString(f, "delattr"))
fooType := newTestClass("Foo", []*Type{ObjectType}, NewDict())
fooForDelAttr := newObject(fooType)
mustNotRaise(nil, SetAttr(f, fooForDelAttr, NewStr("bar"), None))
fun := wrapFuncForTest(func(f *Frame, args ...*Object) (*Object, *BaseException) {
result, raised := delattr.Call(f, args, nil)
if raised != nil {
return nil, raised
}
val, raised := GetAttr(f, args[0], toStrUnsafe(args[1]), nil)
if raised != nil && raised.isInstance(AttributeErrorType) {
f.RestoreExc(nil, nil)
return newTestTuple(result, val == nil).ToObject(), nil
}
return nil, f.RaiseType(AttributeErrorType, fmt.Sprintf("'delattr' failed to remove '%s', got '%s' instead", args[1], val))
})
cases := []invokeTestCase{
{args: wrapArgs(fooForDelAttr, "bar"), want: newTestTuple(None, True.ToObject()).ToObject()},
{args: wrapArgs(fooForDelAttr, "baz"), wantExc: mustCreateException(AttributeErrorType, "'Foo' object has no attribute 'baz'")},
{args: wrapArgs(fooForDelAttr), wantExc: mustCreateException(TypeErrorType, "'delattr' requires 2 arguments")},
{args: wrapArgs(fooForDelAttr, "foo", "bar"), wantExc: mustCreateException(TypeErrorType, "'delattr' requires 2 arguments")},
}
for _, cas := range cases {
if err := runInvokeTestCase(fun, &cas); err != "" {
t.Error(err)
}
}
}
func TestBuiltinFuncs(t *testing.T) {
f := NewRootFrame()
objectDir := ObjectType.dict.Keys(f)
......@@ -359,25 +390,27 @@ func TestBuiltinPrint(t *testing.T) {
}
func TestBuiltinSetAttr(t *testing.T) {
setattr := mustNotRaise(Builtins.GetItemString(NewRootFrame(), "setattr"))
fooType := newTestClass("Foo", []*Type{ObjectType}, newStringDict(map[string]*Object{}))
foo := newObject(fooType)
fun := wrapFuncForTest(func(f *Frame, args ...*Object) (*Object, *BaseException) {
fooObject := newTestClass("Foo", []*Type{ObjectType}, newStringDict(map[string]*Object{})).ToObject()
result, raised := builtinSetAttr(f, append(Args{fooObject}, args...), nil)
result, raised := setattr.Call(f, args, nil)
if raised != nil {
return nil, raised
}
val, raised := GetAttr(f, fooObject, toStrUnsafe(args[0]), nil)
val, raised := GetAttr(f, args[0], toStrUnsafe(args[1]), nil)
if raised != nil {
return nil, raised
}
return newTestTuple(result, val).ToObject(), nil
})
cases := []invokeTestCase{
{args: wrapArgs(), wantExc: mustCreateException(TypeErrorType, "'setattr' requires 3 arguments")},
{args: wrapArgs("foo", "bar"), want: newTestTuple(None, "bar").ToObject()},
{args: wrapArgs("foo", 123), want: newTestTuple(None, 123).ToObject()},
{args: wrapArgs("foo"), wantExc: mustCreateException(TypeErrorType, "'setattr' requires 3 arguments")},
{args: wrapArgs("foo", 123, None), wantExc: mustCreateException(TypeErrorType, "'setattr' requires 3 arguments")},
{args: wrapArgs(123, 123), wantExc: mustCreateException(TypeErrorType, "'setattr' requires a 'str' object but received a \"int\"")},
{args: wrapArgs(foo), wantExc: mustCreateException(TypeErrorType, "'setattr' requires 3 arguments")},
{args: wrapArgs(newObject(fooType), "foo", "bar"), want: newTestTuple(None, "bar").ToObject()},
{args: wrapArgs(newObject(fooType), "foo", 123), want: newTestTuple(None, 123).ToObject()},
{args: wrapArgs(foo, "foo"), wantExc: mustCreateException(TypeErrorType, "'setattr' requires 3 arguments")},
{args: wrapArgs(foo, "foo", 123, None), wantExc: mustCreateException(TypeErrorType, "'setattr' requires 3 arguments")},
{args: wrapArgs(foo, 123, 123), wantExc: mustCreateException(TypeErrorType, "'setattr' requires a 'str' object but received a \"int\"")},
}
for _, cas := range cases {
if err := runInvokeTestCase(fun, &cas); err != "" {
......
......@@ -247,7 +247,7 @@ a, b = NoCmp(1), Cmp(2)
assert cmp(a, b) == -1
assert b.cmp_called
# Test setattr
# Test delattr
class Foo(object):
pass
......@@ -255,6 +255,32 @@ class Foo(object):
setattr(Foo, "a", 1)
assert Foo.a == 1 # pylint: disable=no-member
delattr(Foo, "a")
assert getattr(Foo, "a", None) is None
try:
delattr(Foo, 1, "a")
assert AssertionError
except TypeError:
pass
try:
delattr(Foo)
assert AssertionError
except TypeError:
pass
try:
delattr(Foo, "a", 1)
assert AssertionError
except TypeError:
pass
# Test setattr
setattr(Foo, "a", 1)
assert Foo.a == 1 # pylint: disable=no-member
try:
setattr(Foo, 1, "a")
assert AssertionError
......
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