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