Commit e5da6ef5 authored by Marius Wachtler's avatar Marius Wachtler

object.__str__ use capi slot in order to increase compatibility with cpython

With this change we print True for:
class C(object):
    pass
print C.__str__ is object.__str__

Cheetah depends on this behaviour (see https://bitbucket.org/pypy/compatibility/wiki/cheetah)
parent 38e94b5f
......@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "capi/typeobject.h"
#include "codegen/compvars.h"
#include "runtime/objmodel.h"
#include "runtime/rewrite_args.h"
......@@ -416,26 +417,13 @@ void BoxedMethodDescriptor::gcHandler(GCVisitor* v, Box* _o) {
v->visit(o->type);
}
Box* BoxedWrapperDescriptor::__get__(BoxedWrapperDescriptor* self, Box* inst, Box* owner) {
STAT_TIMER(t0, "us_timer_boxedwrapperdescriptor_get", 20);
RELEASE_ASSERT(self->cls == wrapperdescr_cls, "");
if (inst == None)
return self;
if (!isSubclass(inst->cls, self->type))
raiseExcHelper(TypeError, "Descriptor '' for '%s' objects doesn't apply to '%s' object",
getFullNameOfClass(self->type).c_str(), getFullTypeName(inst).c_str());
return new BoxedWrapperObject(self, inst);
}
Box* BoxedWrapperDescriptor::descr_get(Box* _self, Box* inst, Box* owner) noexcept {
STAT_TIMER(t0, "us_timer_boxedwrapperdescriptor_descr_get", 20);
RELEASE_ASSERT(_self->cls == wrapperdescr_cls, "");
BoxedWrapperDescriptor* self = static_cast<BoxedWrapperDescriptor*>(_self);
if (inst == None)
if (inst == NULL)
return self;
if (!isSubclass(inst->cls, self->type)) {
......@@ -633,14 +621,14 @@ void setupDescr() {
method_cls->giveAttr("__doc__", new (pyston_getset_cls) BoxedGetsetDescriptor(methodGetDoc, NULL, NULL));
method_cls->freeze();
wrapperdescr_cls->giveAttr("__get__",
new BoxedFunction(boxRTFunction((void*)BoxedWrapperDescriptor::__get__, UNKNOWN, 3)));
wrapperdescr_cls->giveAttr("__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperDescriptor::__call__,
UNKNOWN, 2, 0, true, true)));
wrapperdescr_cls->giveAttr("__doc__",
new (pyston_getset_cls) BoxedGetsetDescriptor(wrapperdescrGetDoc, NULL, NULL));
wrapperdescr_cls->freeze();
wrapperdescr_cls->tp_descr_get = BoxedWrapperDescriptor::descr_get;
add_operators(wrapperdescr_cls);
wrapperdescr_cls->freeze();
assert(wrapperdescr_cls->tp_descr_get == BoxedWrapperDescriptor::descr_get);
wrapperobject_cls->giveAttr(
"__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperObject::__call__, UNKNOWN, 1, 0, true, true)));
......
......@@ -1118,12 +1118,12 @@ Box* nondataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, Box
Box* inst = obj;
Box* owner = obj->cls;
Box* r = BoxedWrapperDescriptor::__get__(self, inst, owner);
Box* r = BoxedWrapperDescriptor::descr_get(self, inst, owner);
if (rewrite_args) {
// TODO: inline this?
RewriterVar* r_rtn = rewrite_args->rewriter->call(
/* has_side_effects= */ false, (void*)&BoxedWrapperDescriptor::__get__, r_descr, rewrite_args->obj,
/* has_side_effects= */ false, (void*)&BoxedWrapperDescriptor::descr_get, r_descr, rewrite_args->obj,
r_descr->getAttr(offsetof(Box, cls), Location::forArg(2)));
rewrite_args->out_success = true;
......
......@@ -2506,8 +2506,13 @@ Box* objectRepr(Box* obj) {
return boxString(buf);
}
Box* objectStr(Box* obj) {
return obj->reprIC();
static Box* object_str(Box* obj) noexcept {
try {
return obj->reprIC();
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
Box* objectHash(Box* obj) {
......@@ -3449,7 +3454,6 @@ void setupRuntime() {
FROZENSET = typeFromClass(frozenset_cls);
object_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)objectRepr, UNKNOWN, 1, 0, false, false)));
object_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)objectStr, UNKNOWN, 1, 0, false, false)));
object_cls->giveAttr("__subclasshook__",
boxInstanceMethod(object_cls,
new BoxedFunction(boxRTFunction((void*)objectSubclasshook, UNKNOWN, 2)),
......@@ -3502,9 +3506,15 @@ void setupRuntime() {
object_cls->giveAttr(md.ml_name, new BoxedMethodDescriptor(&md, object_cls));
}
object_cls->giveAttr("__class__", new (pyston_getset_cls) BoxedGetsetDescriptor(objectClass, objectSetClass, NULL));
object_cls->tp_str = object_str;
add_operators(object_cls);
object_cls->freeze();
assert(object_cls->tp_init == object_init);
assert(object_cls->tp_new == object_new);
assert(object_cls->tp_str == object_str);
setupBool();
setupLong();
......
......@@ -945,7 +945,6 @@ public:
DEFAULT_CLASS(wrapperdescr_cls);
static Box* __get__(BoxedWrapperDescriptor* self, Box* inst, Box* owner);
static Box* descr_get(Box* self, Box* inst, Box* owner) noexcept;
static Box* __call__(BoxedWrapperDescriptor* descr, PyObject* self, BoxedTuple* args, Box** _args);
......
class C(object):
pass
print C.__str__ is object.__str__
print type(C).__str__ is object.__str__
print type(None).__str__ is object.__str__
print type(None).__str__ is None.__str__
print type(None.__str__)
print type(type(None).__str__.__get__(None, type(None)))
Subproject commit 56631b487c6bfa7ccd9525cba2a27baff9b6b491
Subproject commit e1d16ce8922700ef6bde50589e84db3a5c095c2b
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