Commit 50143e43 authored by Kevin Modzelewski's avatar Kevin Modzelewski

A number of additions for builtin types

- oldstyle classes get a __dict__
- object().__hash__()
- old style classes __getattribute__
- str.splitlines()
- and file(unicode, unicode)
- start_new_thread takes a third argument
- set.union
- instancemethod __getattr__
parent 0e111b5f
......@@ -129,3 +129,17 @@ string_find(PyStringObject *self, PyObject *args)
return NULL;
return PyInt_FromSsize_t(result);
}
PyObject*
string_splitlines(PyStringObject *self, PyObject *args)
{
int keepends = 0;
if (!PyArg_ParseTuple(args, "|i:splitlines", &keepends))
return NULL;
return stringlib_splitlines(
(PyObject*) self, PyString_AS_STRING(self), PyString_GET_SIZE(self),
keepends
);
}
......@@ -70,8 +70,8 @@ static void* thread_start(Box* target, Box* varargs, Box* kwargs) {
}
// TODO this should take kwargs, which defaults to empty
Box* startNewThread(Box* target, Box* args) {
intptr_t thread_id = start_thread(&thread_start, target, args, NULL);
Box* startNewThread(Box* target, Box* args, Box* kw) {
intptr_t thread_id = start_thread(&thread_start, target, args, kw);
return boxInt(thread_id ^ 0x12345678901L);
}
......@@ -169,9 +169,9 @@ Box* stackSize() {
void setupThread() {
thread_module = createModule("thread", "__builtin__");
thread_module->giveAttr(
"start_new_thread",
new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)startNewThread, BOXED_INT, 2), "start_new_thread"));
thread_module->giveAttr("start_new_thread", new BoxedBuiltinFunctionOrMethod(
boxRTFunction((void*)startNewThread, BOXED_INT, 3, 1, false, false),
"start_new_thread", { NULL }));
thread_module->giveAttr("allocate_lock", new BoxedBuiltinFunctionOrMethod(
boxRTFunction((void*)allocateLock, UNKNOWN, 0), "allocate_lock"));
thread_module->giveAttr(
......
......@@ -127,6 +127,36 @@ Box* classobjCall(Box* _cls, Box* _args, Box* _kwargs) {
return made;
}
static Box* classobjGetattribute(Box* _cls, Box* _attr) {
RELEASE_ASSERT(_cls->cls == classobj_cls, "");
BoxedClassobj* cls = static_cast<BoxedClassobj*>(_cls);
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__")
return makeAttrWrapper(cls);
if (attr->s == "__bases__")
return cls->bases;
if (attr->s == "__name__") {
if (cls->name)
return cls->name;
return None;
}
}
Box* r = classLookup(cls, attr->s);
if (!r)
raiseExcHelper(AttributeError, "class %s has no attribute '%s'", cls->name->s.c_str(), attr->s.c_str());
r = processDescriptor(r, None, cls);
return r;
}
Box* classobjStr(Box* _obj) {
if (!isSubclass(_obj->cls, classobj_cls)) {
raiseExcHelper(TypeError, "descriptor '__str__' requires a 'classobj' object but received an '%s'",
......@@ -148,7 +178,7 @@ static Box* _instanceGetattribute(Box* _inst, Box* _attr, bool raise_on_missing)
RELEASE_ASSERT(_attr->cls == str_cls, "");
BoxedString* attr = static_cast<BoxedString*>(_attr);
// TODO: special handling for accessing __dict__ and __class__
// These are special cases in CPython as well:
if (attr->s[0] == '_' && attr->s[1] == '_') {
if (attr->s == "__dict__")
return makeAttrWrapper(inst);
......@@ -340,7 +370,10 @@ void setupClassobj() {
classobj_cls->giveAttr("__call__",
new BoxedFunction(boxRTFunction((void*)classobjCall, UNKNOWN, 1, 0, true, true)));
classobj_cls->giveAttr("__getattribute__",
new BoxedFunction(boxRTFunction((void*)classobjGetattribute, UNKNOWN, 2)));
classobj_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)classobjStr, STR, 1)));
classobj_cls->giveAttr("__dict__", dict_descr);
classobj_cls->freeze();
......
......@@ -647,6 +647,12 @@ Box* fileExit(BoxedFile* self, Box* exc_type, Box* exc_val, Box** args) {
Box* fileNew(BoxedClass* cls, Box* s, Box* m) {
assert(cls == file_cls);
if (s->cls == unicode_cls)
s = _PyUnicode_AsDefaultEncodedString(s, NULL);
if (m->cls == unicode_cls)
m = _PyUnicode_AsDefaultEncodedString(m, NULL);
if (s->cls != str_cls) {
fprintf(stderr, "TypeError: coercing to Unicode: need string of buffer, %s found\n", getTypeName(s));
raiseExcHelper(TypeError, "");
......
......@@ -861,7 +861,7 @@ extern "C" Box* intNeg(BoxedInt* v) {
extern "C" Box* intNonzero(BoxedInt* v) {
if (!isSubclass(v->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__nonzer__' requires a 'int' object but received a '%s'",
raiseExcHelper(TypeError, "descriptor '__nonzero__' requires a 'int' object but received a '%s'",
getTypeName(v));
return boxBool(v->n != 0);
......
......@@ -1484,6 +1484,12 @@ Box* getattrInternalGeneral(Box* obj, const std::string& attr, GetattrRewriteArg
return descr;
}
// TODO this shouldn't go here; it should be in instancemethod_cls->tp_getattr[o]
if (obj->cls == instancemethod_cls) {
assert(!rewrite_args || !rewrite_args->out_success);
return getattrInternalGeneral(static_cast<BoxedInstanceMethod*>(obj)->func, attr, NULL, cls_only, for_call,
bind_obj_out, NULL);
}
// Finally, check __getattr__
if (!cls_only) {
......@@ -1928,7 +1934,9 @@ extern "C" BoxedInt* hash(Box* obj) {
Box* hash = getclsattr_internal(obj, "__hash__", NULL);
if (hash == NULL) {
ASSERT(isUserDefined(obj->cls) || obj->cls == function_cls, "%s.__hash__", getTypeName(obj));
ASSERT(isUserDefined(obj->cls) || obj->cls == function_cls || obj->cls == object_cls
|| obj->cls == classobj_cls,
"%s.__hash__", getTypeName(obj));
// TODO not the best way to handle this...
return static_cast<BoxedInt*>(boxInt((i64)obj));
}
......
......@@ -231,6 +231,22 @@ Box* setUpdate(BoxedSet* self, BoxedTuple* args) {
return None;
}
Box* setUnion(BoxedSet* self, BoxedTuple* args) {
if (!isSubclass(self->cls, set_cls))
raiseExcHelper(TypeError, "descriptor 'union' requires a 'set' object but received a '%s'", getTypeName(self));
BoxedSet* rtn = new BoxedSet();
rtn->s.insert(self->s.begin(), self->s.end());
for (auto container : args->pyElements()) {
for (auto elt : container->pyElements()) {
rtn->s.insert(elt);
}
}
return rtn;
}
Box* setCopy(BoxedSet* self) {
assert(self->cls == set_cls);
......@@ -320,6 +336,7 @@ void setupSet() {
set_cls->giveAttr("clear", new BoxedFunction(boxRTFunction((void*)setClear, NONE, 1)));
set_cls->giveAttr("update", new BoxedFunction(boxRTFunction((void*)setUpdate, NONE, 1, 0, true, false)));
set_cls->giveAttr("union", new BoxedFunction(boxRTFunction((void*)setUnion, UNKNOWN, 1, 0, true, false)));
set_cls->giveAttr("copy", new BoxedFunction(boxRTFunction((void*)setCopy, UNKNOWN, 1)));
......
......@@ -39,6 +39,7 @@ extern "C" PyObject* string_split(PyStringObject* self, PyObject* args) noexcept
extern "C" PyObject* string_rsplit(PyStringObject* self, PyObject* args) noexcept;
extern "C" PyObject* string_find(PyStringObject* self, PyObject* args) noexcept;
extern "C" PyObject* string_rfind(PyStringObject* self, PyObject* args) noexcept;
extern "C" PyObject* string_splitlines(PyStringObject* self, PyObject* args) noexcept;
namespace pyston {
......@@ -2438,6 +2439,7 @@ static PyMethodDef string_methods[] = {
{ "find", (PyCFunction)string_find, METH_VARARGS, NULL },
{ "rfind", (PyCFunction)string_rfind, METH_VARARGS, NULL },
{ "expandtabs", (PyCFunction)string_expandtabs, METH_VARARGS, NULL },
{ "splitlines", (PyCFunction)string_splitlines, METH_VARARGS, NULL },
};
void setupStr() {
......
......@@ -6,3 +6,7 @@ print hash(1)
i = hash("hello world")
j = hash("hello" + " world")
print i == j
o1 = object()
o2 = object()
print hash(o1) == hash(o2)
# expected: fail
# - not implemented
# Instance methods forward any missed attribute lookups to their underlying function
class C(object):
......@@ -16,3 +13,4 @@ im = c.f
print type(f), type(im)
f.a = 1
print im.a
print im.__name__
......@@ -147,3 +147,22 @@ class Hashable:
print hash(Hashable())
del Hashable.__hash__
print type(hash(Hashable()))
class C():
def foo(self):
pass
@classmethod
def bar(cls):
print cls
c = C()
print type(C.foo)
print type(getattr(C, "foo"))
print type(getattr(C, "foo").im_func)
c.bar()
C.bar()
try:
C.doesnt_exist
except AttributeError as e:
print e
......@@ -79,3 +79,9 @@ s = set([])
s2 = s.copy()
s.add(1)
print s, s2
s1 = set([3])
s2 = set([1])
print sorted(s1.union(s2))
print sorted(s1.union(range(5, 7)))
print s2.union([], [], [], [])
......@@ -10,3 +10,11 @@ def show(obj):
print sorted(obj.__dict__.items())
show(object())
class C: # oldstyle
pass
print C.__dict__["__module__"]
print len(C().__dict__)
# show(C)
# show(C())
......@@ -145,3 +145,6 @@ print "hello world".endswith(("x", "h"))
print "a.b.c.d".partition('.')
print "a.b.c.d".rpartition('.')
print 'ab c\n\nde fg\rkl\r\n'.splitlines()
print 'ab c\n\nde fg\rkl\r\n'.splitlines(True)
......@@ -23,6 +23,12 @@ while not done:
print "done!"
done = False
with print_lock:
t = start_new_thread(run, (), {'arg': 6})
while not done:
time.sleep(0)
l = allocate_lock()
print l.acquire()
print l.acquire(0)
......
......@@ -96,3 +96,6 @@ print unichr(97)
print "hello world".split(u'l')
print "hello world".rsplit(u'l')
with open(u"/dev/null", u"r") as f:
print f.read()
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