Commit e6a5b93c authored by Kevin Modzelewski's avatar Kevin Modzelewski

Add instance_cls.__delattr__, __iter__, and next

gflags test is passing

Also add file.name
parent 232abd9e
...@@ -636,9 +636,9 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ ...@@ -636,9 +636,9 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
is an iterator, this returns itself. */ is an iterator, this returns itself. */
#define PyIter_Check(obj) \ #define PyIter_Check(obj) \
(PyType_HasFeature((obj)->ob_type, Py_TPFLAGS_HAVE_ITER) && \ (PyType_HasFeature(Py_TYPE((obj)), Py_TPFLAGS_HAVE_ITER) && \
(obj)->ob_type->tp_iternext != NULL && \ Py_TYPE((obj))->tp_iternext != NULL && \
(obj)->ob_type->tp_iternext != &_PyObject_NextNotImplemented) Py_TYPE((obj))->tp_iternext != &_PyObject_NextNotImplemented)
PyAPI_FUNC(PyObject *) PyIter_Next(PyObject *) PYSTON_NOEXCEPT; PyAPI_FUNC(PyObject *) PyIter_Next(PyObject *) PYSTON_NOEXCEPT;
/* Takes an iterator object and calls its tp_iternext slot, /* Takes an iterator object and calls its tp_iternext slot,
......
...@@ -333,6 +333,34 @@ Box* instanceSetattr(Box* _inst, Box* _attr, Box* value) { ...@@ -333,6 +333,34 @@ Box* instanceSetattr(Box* _inst, Box* _attr, Box* value) {
return None; return None;
} }
Box* instanceDelattr(Box* _inst, Box* _attr) {
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__")
raiseExcHelper(TypeError, "__dict__ must be set to a dictionary");
if (attr->s == "__class__")
raiseExcHelper(TypeError, "__class__ must be set to a class");
}
static const std::string delattr_str("__delattr__");
Box* delattr = classLookup(inst->inst_cls, delattr_str);
if (delattr) {
delattr = processDescriptor(delattr, inst, inst->inst_cls);
return runtimeCall(delattr, ArgPassSpec(1), _attr, NULL, NULL, NULL, NULL);
}
_inst->delattr(attr->s, NULL);
return None;
}
static int instance_setattro(Box* cls, Box* attr, Box* value) noexcept { static int instance_setattro(Box* cls, Box* attr, Box* value) noexcept {
try { try {
if (value) { if (value) {
...@@ -488,6 +516,45 @@ static Box* instanceHash(BoxedInstance* inst) { ...@@ -488,6 +516,45 @@ static Box* instanceHash(BoxedInstance* inst) {
} }
} }
static Box* instanceIter(BoxedInstance* self) {
assert(self->cls == instance_cls);
PyObject* func;
if ((func = _instanceGetattribute(self, boxStrConstant("__iter__"), false)) != NULL) {
PyObject* res = PyEval_CallObject(func, (PyObject*)NULL);
if (!res)
throwCAPIException();
if (!PyIter_Check(res))
raiseExcHelper(TypeError, "__iter__ returned non-iterator of type '%.100s'", res->cls->tp_name);
return res;
}
if ((func = _instanceGetattribute(self, boxStrConstant("__getitem__"), false)) == NULL) {
raiseExcHelper(TypeError, "iteration over non-sequence");
}
Box* r = PySeqIter_New((PyObject*)self);
if (!r)
throwCAPIException();
return r;
}
static Box* instanceNext(BoxedInstance* inst) {
assert(inst->cls == instance_cls);
Box* next_func = _instanceGetattribute(inst, boxStrConstant("next"), false);
if (!next_func) {
// not 100% sure why this is a different error:
raiseExcHelper(TypeError, "instance has no next() method");
}
Box* r = runtimeCall(next_func, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
return r;
}
static PyObject* instance_index(PyObject* self) noexcept { static PyObject* instance_index(PyObject* self) noexcept {
PyObject* func, *res; PyObject* func, *res;
/* /*
...@@ -569,6 +636,7 @@ void setupClassobj() { ...@@ -569,6 +636,7 @@ void setupClassobj() {
instance_cls->giveAttr("__getattribute__", instance_cls->giveAttr("__getattribute__",
new BoxedFunction(boxRTFunction((void*)instanceGetattribute, UNKNOWN, 2))); new BoxedFunction(boxRTFunction((void*)instanceGetattribute, UNKNOWN, 2)));
instance_cls->giveAttr("__setattr__", new BoxedFunction(boxRTFunction((void*)instanceSetattr, UNKNOWN, 3))); instance_cls->giveAttr("__setattr__", new BoxedFunction(boxRTFunction((void*)instanceSetattr, UNKNOWN, 3)));
instance_cls->giveAttr("__delattr__", new BoxedFunction(boxRTFunction((void*)instanceDelattr, UNKNOWN, 2)));
instance_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)instanceStr, UNKNOWN, 1))); 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("__repr__", new BoxedFunction(boxRTFunction((void*)instanceRepr, UNKNOWN, 1)));
instance_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)instanceNonzero, UNKNOWN, 1))); instance_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)instanceNonzero, UNKNOWN, 1)));
...@@ -578,6 +646,8 @@ void setupClassobj() { ...@@ -578,6 +646,8 @@ void setupClassobj() {
instance_cls->giveAttr("__delitem__", new BoxedFunction(boxRTFunction((void*)instanceDelitem, UNKNOWN, 2))); instance_cls->giveAttr("__delitem__", new BoxedFunction(boxRTFunction((void*)instanceDelitem, UNKNOWN, 2)));
instance_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)instanceContains, UNKNOWN, 2))); instance_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)instanceContains, UNKNOWN, 2)));
instance_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)instanceHash, UNKNOWN, 1))); instance_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)instanceHash, UNKNOWN, 1)));
instance_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction((void*)instanceIter, UNKNOWN, 1)));
instance_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)instanceNext, UNKNOWN, 1)));
instance_cls->giveAttr("__call__", instance_cls->giveAttr("__call__",
new BoxedFunction(boxRTFunction((void*)instanceCall, UNKNOWN, 1, 0, true, true))); new BoxedFunction(boxRTFunction((void*)instanceCall, UNKNOWN, 1, 0, true, true)));
instance_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)instanceEq, UNKNOWN, 2))); instance_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)instanceEq, UNKNOWN, 2)));
......
...@@ -1647,6 +1647,8 @@ void setupFile() { ...@@ -1647,6 +1647,8 @@ void setupFile() {
file_cls->giveAttr("tell", new BoxedFunction(boxRTFunction((void*)fileTell, UNKNOWN, 1))); file_cls->giveAttr("tell", new BoxedFunction(boxRTFunction((void*)fileTell, UNKNOWN, 1)));
file_cls->giveAttr("softspace", file_cls->giveAttr("softspace",
new BoxedMemberDescriptor(BoxedMemberDescriptor::INT, offsetof(BoxedFile, f_softspace), false)); new BoxedMemberDescriptor(BoxedMemberDescriptor::INT, offsetof(BoxedFile, f_softspace), false));
file_cls->giveAttr("name",
new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedFile, f_name), true));
file_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)fileNew, UNKNOWN, 4, 2, false, false), file_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)fileNew, UNKNOWN, 4, 2, false, false),
{ boxStrConstant("r"), boxInt(-1) })); { boxStrConstant("r"), boxInt(-1) }));
......
...@@ -320,13 +320,10 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset ...@@ -320,13 +320,10 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
tp_basicsize = instance_size; tp_basicsize = instance_size;
tp_weaklistoffset = weaklist_offset; tp_weaklistoffset = weaklist_offset;
tp_flags |= Py_TPFLAGS_DEFAULT_EXTERNAL;
tp_flags |= Py_TPFLAGS_CHECKTYPES; tp_flags |= Py_TPFLAGS_CHECKTYPES;
tp_flags |= Py_TPFLAGS_BASETYPE; tp_flags |= Py_TPFLAGS_BASETYPE;
tp_flags |= Py_TPFLAGS_HAVE_CLASS;
tp_flags |= Py_TPFLAGS_HAVE_GC; tp_flags |= Py_TPFLAGS_HAVE_GC;
tp_flags |= Py_TPFLAGS_HAVE_WEAKREFS;
tp_flags |= Py_TPFLAGS_HAVE_RICHCOMPARE;
tp_flags |= Py_TPFLAGS_HAVE_INDEX;
if (base && (base->tp_flags & Py_TPFLAGS_HAVE_NEWBUFFER)) if (base && (base->tp_flags & Py_TPFLAGS_HAVE_NEWBUFFER))
tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER; tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
......
...@@ -3,6 +3,7 @@ import tempfile ...@@ -3,6 +3,7 @@ import tempfile
f = open("/dev/null") f = open("/dev/null")
print repr(f.read()) print repr(f.read())
print repr(f.name)
f2 = file("/dev/null") f2 = file("/dev/null")
print repr(f2.read()) print repr(f2.read())
......
...@@ -147,9 +147,13 @@ class SetattrTest: ...@@ -147,9 +147,13 @@ class SetattrTest:
def __setattr__(self, attr, value): def __setattr__(self, attr, value):
print "setattr", attr, value print "setattr", attr, value
def __delattr__(self, attr):
print "delattr", attr
s = SetattrTest() s = SetattrTest()
s.b = 2 s.b = 2
print g.__dict__.items() print s.__dict__.items()
del s.b
class MappingTest: class MappingTest:
def __getitem__(self, key): def __getitem__(self, key):
...@@ -245,3 +249,29 @@ class E(C, object): ...@@ -245,3 +249,29 @@ class E(C, object):
print issubclass(D, C), isinstance(D(), C) print issubclass(D, C), isinstance(D(), C)
print issubclass(E, C), isinstance(E(), C) print issubclass(E, C), isinstance(E(), C)
print isinstance(E, object), isinstance(E(), object) print isinstance(E, object), isinstance(E(), object)
class SeqTest:
class Iterator:
def __init__(self):
self.n = 5
def next(self):
print "next"
if self.n <= 0:
raise StopIteration()
r = self.n
self.n -= 1
return r
def __iter__(self):
print "iter"
return SeqTest.Iterator()
m = SeqTest()
print list(m)
class OldSeqTest:
def __getitem__(self, n):
print "getitem", n
if n > 5:
raise IndexError()
return n ** 2
m = OldSeqTest()
print list(m)
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