Commit 075620c7 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Add instance.__setattr__

Including the ability to set __class__
parent 9f63b62e
......@@ -225,6 +225,39 @@ Box* instanceGetattribute(Box* _inst, Box* _attr) {
return _instanceGetattribute(_inst, _attr, true);
}
Box* instanceSetattr(Box* _inst, Box* _attr, Box* value) {
RELEASE_ASSERT(_inst->cls == instance_cls, "");
BoxedInstance* inst = static_cast<BoxedInstance*>(_inst);
RELEASE_ASSERT(_attr->cls == str_cls, "");
BoxedString* attr = static_cast<BoxedString*>(_attr);
// These are special cases in CPython as well:
if (attr->s[0] == '_' && attr->s[1] == '_') {
if (attr->s == "__dict__")
Py_FatalError("unimplemented");
if (attr->s == "__class__") {
if (value->cls != classobj_cls)
raiseExcHelper(TypeError, "__class__ must be set to a class");
inst->inst_cls = static_cast<BoxedClassobj*>(value);
return None;
}
}
static const std::string setattr_str("__setattr__");
Box* setattr = classLookup(inst->inst_cls, setattr_str);
if (setattr) {
setattr = processDescriptor(setattr, inst, inst->inst_cls);
return runtimeCall(setattr, ArgPassSpec(2), _attr, value, NULL, NULL, NULL);
}
_inst->setattr(attr->s, value, NULL);
return None;
}
Box* instanceRepr(Box* _inst) {
RELEASE_ASSERT(_inst->cls == instance_cls, "");
BoxedInstance* inst = static_cast<BoxedInstance*>(_inst);
......@@ -389,6 +422,7 @@ void setupClassobj() {
instance_cls->giveAttr("__getattribute__",
new BoxedFunction(boxRTFunction((void*)instanceGetattribute, UNKNOWN, 2)));
instance_cls->giveAttr("__setattr__", new BoxedFunction(boxRTFunction((void*)instanceSetattr, UNKNOWN, 3)));
instance_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)instanceStr, UNKNOWN, 1)));
instance_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)instanceRepr, UNKNOWN, 1)));
instance_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)instanceNonzero, UNKNOWN, 1)));
......
......@@ -18,3 +18,25 @@ try:
c.__class__ = 1
except TypeError as e:
print e
# Same thing but for old-style classes:
class C():
def foo(self):
print "C.foo()"
class D():
def foo(self):
print "D.foo()"
c = C()
c.foo()
c.__class__ = D
c.foo()
try:
c.__class__ = 1
except TypeError as e:
print e
......@@ -125,6 +125,14 @@ print g.__class__
print g.__dict__.items()
print bool(g)
class SetattrTest:
def __setattr__(self, attr, value):
print "setattr", attr, value
s = SetattrTest()
s.b = 2
print g.__dict__.items()
class MappingTest:
def __getitem__(self, key):
print "getitem", key
......
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