Commit 1c630103 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Slightly change delattr behavior and messages

Not worth producing CPython's error messages exactly: some delattr
messages depend on whether or not the object has a __dict__ allocated
or not.  Just canonicalize those in the tester.
parent 5e625bbd
......@@ -2685,7 +2685,7 @@ extern "C" void delattr_internal(Box* obj, const std::string& attr, bool allow_c
}
// first check wether the deleting attribute is a descriptor
Box* clsAttr = getattr_internal(obj, attr, true, false, NULL, NULL);
Box* clsAttr = typeLookup(obj->cls, attr, NULL, NULL);
if (clsAttr != NULL) {
Box* delAttr = getattr_internal(clsAttr, delete_str, false, true, NULL, NULL);
......@@ -2703,7 +2703,8 @@ extern "C" void delattr_internal(Box* obj, const std::string& attr, bool allow_c
} else {
// the exception cpthon throws is different when the class contains the attribute
if (clsAttr != NULL) {
raiseExcHelper(AttributeError, attr.c_str());
raiseExcHelper(AttributeError, "'%s' object attribute '%s' is read-only", getTypeName(obj)->c_str(),
attr.c_str());
} else {
raiseAttributeError(obj, attr.c_str());
}
......@@ -2721,12 +2722,9 @@ extern "C" void delattr(Box* obj, const char* attr) {
raiseExcHelper(TypeError, "can't set attributes of built-in/extension type '%s'\n",
getNameOfClass(cobj)->c_str());
}
} else {
if (!isUserDefined(obj->cls)) {
raiseExcHelper(AttributeError, "'%s' object attribute '%s' is read-only", getTypeName(obj)->c_str(), attr);
}
}
delattr_internal(obj, attr, true, NULL);
}
......@@ -2875,7 +2873,7 @@ Box* typeCallInternal(BoxedFunction* f, CallRewriteArgs* rewrite_args, ArgPassSp
// If this is true, not supposed to call __init__:
RELEASE_ASSERT(made->cls == ccls, "allowed but unsupported");
if (init_attr) {
if (init_attr && init_attr != typeLookup(object_cls, _init_str, NULL, NULL)) {
Box* initrtn;
if (rewrite_args) {
CallRewriteArgs srewrite_args(rewrite_args->rewriter, r_init);
......
......@@ -468,7 +468,8 @@ Box* objectNew(BoxedClass* cls, BoxedTuple* args) {
assert(args->cls == tuple_cls);
if (args->elts.size() != 0) {
if (typeLookup(cls, "__init__", NULL, NULL) == NULL)
// TODO slow
if (typeLookup(cls, "__init__", NULL, NULL) == typeLookup(object_cls, "__init__", NULL, NULL))
raiseExcHelper(TypeError, "object.__new__() takes no parameters");
}
......@@ -480,6 +481,10 @@ Box* objectNew(BoxedClass* cls, BoxedTuple* args) {
return rtn;
}
Box* objectInit(Box* b, BoxedTuple* args) {
return None;
}
bool TRACK_ALLOCATIONS = false;
void setupRuntime() {
gc::registerStaticRootObj(HiddenClass::getRoot());
......@@ -539,6 +544,7 @@ void setupRuntime() {
object_cls->giveAttr("__name__", boxStrConstant("object"));
object_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)objectNew, UNKNOWN, 1, 0, true, false)));
object_cls->giveAttr("__init__", new BoxedFunction(boxRTFunction((void*)objectInit, UNKNOWN, 1, 0, true, false)));
object_cls->freeze();
auto typeCallObj = boxRTFunction((void*)typeCall, UNKNOWN, 1, 0, true, false);
......
......@@ -7,6 +7,13 @@ def del_builtin_attr(o):
#print repr(e)
print e
try:
del a.aaaa
print "error"
except AttributeError, e:
#print repr(e)
print e
a=1
del_builtin_attr(a)
a=1.0
......@@ -79,7 +86,7 @@ try:
del a.speak
print "del func error"
except AttributeError, e:
print "del func:%s"%(e)
print "del func"
del AttrClass.speak
try:
......
......@@ -91,10 +91,11 @@ def canonicalize_stderr(stderr):
substitutions = [
("NameError: global name '", "NameError: name '"),
("AttributeError: '(\w+)' object attribute '(\w+)' is read-only", "AttributeError: \\2"),
]
for pattern, subst_with in substitutions:
stderr = stderr.replace(pattern, subst_with)
stderr = re.sub(pattern, subst_with, stderr)
return stderr
......
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