Commit ae7d1671 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Number of small compatibility fixes

Add file.isatty
sys.exit(None) -> exit code 0
non-dict kwargs
hash(function)
CPython's implementation of PyCallIter
parent 3ec5c835
...@@ -293,7 +293,7 @@ STDLIB_RELEASE_OBJS := stdlib.release.bc.o ...@@ -293,7 +293,7 @@ STDLIB_RELEASE_OBJS := stdlib.release.bc.o
ASM_SRCS := $(wildcard src/runtime/*.S) ASM_SRCS := $(wildcard src/runtime/*.S)
STDMODULE_SRCS := errnomodule.c shamodule.c sha256module.c sha512module.c _math.c mathmodule.c md5.c md5module.c _randommodule.c _sre.c operator.c binascii.c pwdmodule.c posixmodule.c _struct.c datetimemodule.c _functoolsmodule.c _collectionsmodule.c itertoolsmodule.c resource.c signalmodule.c selectmodule.c fcntlmodule.c timemodule.c arraymodule.c zlibmodule.c _codecsmodule.c socketmodule.c unicodedata.c _weakref.c cStringIO.c _io/bufferedio.c _io/bytesio.c _io/fileio.c _io/iobase.c _io/_iomodule.c _io/stringio.c _io/textio.c $(EXTRA_STDMODULE_SRCS) STDMODULE_SRCS := errnomodule.c shamodule.c sha256module.c sha512module.c _math.c mathmodule.c md5.c md5module.c _randommodule.c _sre.c operator.c binascii.c pwdmodule.c posixmodule.c _struct.c datetimemodule.c _functoolsmodule.c _collectionsmodule.c itertoolsmodule.c resource.c signalmodule.c selectmodule.c fcntlmodule.c timemodule.c arraymodule.c zlibmodule.c _codecsmodule.c socketmodule.c unicodedata.c _weakref.c cStringIO.c _io/bufferedio.c _io/bytesio.c _io/fileio.c _io/iobase.c _io/_iomodule.c _io/stringio.c _io/textio.c $(EXTRA_STDMODULE_SRCS)
STDOBJECT_SRCS := structseq.c capsule.c stringobject.c exceptions.c unicodeobject.c unicodectype.c bytearrayobject.c bytes_methods.c weakrefobject.c memoryobject.c $(EXTRA_STDOBJECT_SRCS) STDOBJECT_SRCS := structseq.c capsule.c stringobject.c exceptions.c unicodeobject.c unicodectype.c bytearrayobject.c bytes_methods.c weakrefobject.c memoryobject.c iterobject.c $(EXTRA_STDOBJECT_SRCS)
STDPYTHON_SRCS := pyctype.c getargs.c formatter_string.c pystrtod.c dtoa.c formatter_unicode.c structmember.c $(EXTRA_STDPYTHON_SRCS) STDPYTHON_SRCS := pyctype.c getargs.c formatter_string.c pystrtod.c dtoa.c formatter_unicode.c structmember.c $(EXTRA_STDPYTHON_SRCS)
FROM_CPYTHON_SRCS := $(addprefix from_cpython/Modules/,$(STDMODULE_SRCS)) $(addprefix from_cpython/Objects/,$(STDOBJECT_SRCS)) $(addprefix from_cpython/Python/,$(STDPYTHON_SRCS)) FROM_CPYTHON_SRCS := $(addprefix from_cpython/Modules/,$(STDMODULE_SRCS)) $(addprefix from_cpython/Objects/,$(STDOBJECT_SRCS)) $(addprefix from_cpython/Python/,$(STDPYTHON_SRCS))
......
...@@ -18,7 +18,7 @@ add_custom_target(copy_stdlib ALL DEPENDS ${STDLIB_TARGETS}) ...@@ -18,7 +18,7 @@ add_custom_target(copy_stdlib ALL DEPENDS ${STDLIB_TARGETS})
file(GLOB_RECURSE STDMODULE_SRCS Modules errnomodule.c shamodule.c sha256module.c sha512module.c _math.c mathmodule.c md5.c md5module.c _randommodule.c _sre.c operator.c binascii.c pwdmodule.c posixmodule.c _struct.c datetimemodule.c _functoolsmodule.c _collectionsmodule.c itertoolsmodule.c resource.c signalmodule.c selectmodule.c fcntlmodule.c timemodule.c arraymodule.c zlibmodule.c _codecsmodule.c socketmodule.c unicodedata.c _weakref.c cStringIO.c bufferedio.c bytesio.c fileio.c iobase.c _iomodule.c stringio.c textio.c) file(GLOB_RECURSE STDMODULE_SRCS Modules errnomodule.c shamodule.c sha256module.c sha512module.c _math.c mathmodule.c md5.c md5module.c _randommodule.c _sre.c operator.c binascii.c pwdmodule.c posixmodule.c _struct.c datetimemodule.c _functoolsmodule.c _collectionsmodule.c itertoolsmodule.c resource.c signalmodule.c selectmodule.c fcntlmodule.c timemodule.c arraymodule.c zlibmodule.c _codecsmodule.c socketmodule.c unicodedata.c _weakref.c cStringIO.c bufferedio.c bytesio.c fileio.c iobase.c _iomodule.c stringio.c textio.c)
# compile specified files in from_cpython/Objects # compile specified files in from_cpython/Objects
file(GLOB_RECURSE STDOBJECT_SRCS Objects structseq.c capsule.c stringobject.c exceptions.c unicodeobject.c unicodectype.c bytearrayobject.c bytes_methods.c weakrefobject.c memoryobject.c) file(GLOB_RECURSE STDOBJECT_SRCS Objects structseq.c capsule.c stringobject.c exceptions.c unicodeobject.c unicodectype.c bytearrayobject.c bytes_methods.c weakrefobject.c memoryobject.c iterobject.c)
# compile specified files in from_cpython/Python # compile specified files in from_cpython/Python
file(GLOB_RECURSE STDPYTHON_SRCS Python getargs.c pyctype.c formatter_string.c pystrtod.c dtoa.c formatter_unicode.c structmember.c) file(GLOB_RECURSE STDPYTHON_SRCS Python getargs.c pyctype.c formatter_string.c pystrtod.c dtoa.c formatter_unicode.c structmember.c)
......
...@@ -14,8 +14,7 @@ extern "C" { ...@@ -14,8 +14,7 @@ extern "C" {
PyAPI_FUNC(PyObject *) PySeqIter_New(PyObject *) PYSTON_NOEXCEPT; PyAPI_FUNC(PyObject *) PySeqIter_New(PyObject *) PYSTON_NOEXCEPT;
// Pyston change: this is no longer a static object PyAPI_DATA(PyTypeObject) PyCallIter_Type;
//PyAPI_DATA(PyTypeObject) PyCallIter_Type;
#define PyCallIter_Check(op) (Py_TYPE(op) == &PyCallIter_Type) #define PyCallIter_Check(op) (Py_TYPE(op) == &PyCallIter_Type)
......
// This file is originally from CPython 2.7, with modifications for Pyston
// (actually it's just a subset of the CPython version)
#include "Python.h"
extern PyTypeObject PyCallIter_Type;
typedef struct {
PyObject_HEAD
PyObject *it_callable; /* Set to NULL when iterator is exhausted */
PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */
} calliterobject;
PyObject *
PyCallIter_New(PyObject *callable, PyObject *sentinel)
{
calliterobject *it;
it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
if (it == NULL)
return NULL;
Py_INCREF(callable);
it->it_callable = callable;
Py_INCREF(sentinel);
it->it_sentinel = sentinel;
_PyObject_GC_TRACK(it);
return (PyObject *)it;
}
static void
calliter_dealloc(calliterobject *it)
{
_PyObject_GC_UNTRACK(it);
Py_XDECREF(it->it_callable);
Py_XDECREF(it->it_sentinel);
PyObject_GC_Del(it);
}
static int
calliter_traverse(calliterobject *it, visitproc visit, void *arg)
{
Py_VISIT(it->it_callable);
Py_VISIT(it->it_sentinel);
return 0;
}
static PyObject *
calliter_iternext(calliterobject *it)
{
if (it->it_callable != NULL) {
PyObject *args = PyTuple_New(0);
PyObject *result;
if (args == NULL)
return NULL;
result = PyObject_Call(it->it_callable, args, NULL);
Py_DECREF(args);
if (result != NULL) {
int ok;
ok = PyObject_RichCompareBool(result,
it->it_sentinel,
Py_EQ);
if (ok == 0)
return result; /* Common case, fast path */
Py_DECREF(result);
if (ok > 0) {
Py_CLEAR(it->it_callable);
Py_CLEAR(it->it_sentinel);
}
}
else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
PyErr_Clear();
Py_CLEAR(it->it_callable);
Py_CLEAR(it->it_sentinel);
}
}
return NULL;
}
PyTypeObject PyCallIter_Type = {
// Pyston change:
PyVarObject_HEAD_INIT(NULL /* &PyType_Type */, 0)
"callable-iterator", /* tp_name */
sizeof(calliterobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)calliter_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
(traverseproc)calliter_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)calliter_iternext, /* tp_iternext */
0, /* tp_methods */
};
...@@ -45,23 +45,28 @@ ...@@ -45,23 +45,28 @@
#error #error
#endif #endif
using namespace pyston; namespace pyston {
// returns true iff we got a request to exit, i.e. SystemExit, placing the // returns true iff we got a request to exit, i.e. SystemExit, placing the
// return code in `*retcode`. does not touch `*retcode* if it returns false. // return code in `*retcode`. does not touch `*retcode* if it returns false.
static bool handle_toplevel_exn(const ExcInfo& e, int* retcode) { static bool handle_toplevel_exn(const ExcInfo& e, int* retcode) {
if (e.matches(SystemExit)) { if (e.matches(SystemExit)) {
Box* code = e.value->getattr("code"); Box* code = e.value->getattr("code");
*retcode = 1;
if (code && isSubclass(code->cls, pyston::int_cls)) if (!code || code == None)
*retcode = 0;
else if (isSubclass(code->cls, int_cls))
*retcode = static_cast<BoxedInt*>(code)->n; *retcode = static_cast<BoxedInt*>(code)->n;
else
*retcode = 1;
return true; return true;
} }
e.printExcAndTraceback(); e.printExcAndTraceback();
return false; return false;
} }
int main(int argc, char** argv) { static int main(int argc, char** argv) {
Timer _t("for jit startup"); Timer _t("for jit startup");
// llvm::sys::PrintStackTraceOnErrorSignal(); // llvm::sys::PrintStackTraceOnErrorSignal();
// llvm::PrettyStackTraceProgram X(argc, argv); // llvm::PrettyStackTraceProgram X(argc, argv);
...@@ -259,3 +264,9 @@ int main(int argc, char** argv) { ...@@ -259,3 +264,9 @@ int main(int argc, char** argv) {
return rtncode; return rtncode;
} }
} // namespace pyston
int main(int argc, char** argv) {
return pyston::main(argc, argv);
}
...@@ -852,10 +852,6 @@ extern "C" PyObject* PyImport_Import(PyObject* module_name) noexcept { ...@@ -852,10 +852,6 @@ extern "C" PyObject* PyImport_Import(PyObject* module_name) noexcept {
} }
extern "C" PyObject* PyCallIter_New(PyObject* callable, PyObject* sentinel) noexcept {
Py_FatalError("unimplemented");
}
extern "C" void* PyObject_Malloc(size_t sz) noexcept { extern "C" void* PyObject_Malloc(size_t sz) noexcept {
return gc_compat_malloc(sz); return gc_compat_malloc(sz);
} }
......
...@@ -57,6 +57,7 @@ public: ...@@ -57,6 +57,7 @@ public:
Box* dictViewKeysIter(Box* self); Box* dictViewKeysIter(Box* self);
Box* dictViewValuesIter(Box* self); Box* dictViewValuesIter(Box* self);
Box* dictViewItemsIter(Box* self); Box* dictViewItemsIter(Box* self);
void dictMerge(BoxedDict* self, Box* other);
} }
#endif #endif
...@@ -1055,14 +1055,27 @@ extern "C" size_t Py_UniversalNewlineFread(char* buf, size_t n, FILE* stream, Py ...@@ -1055,14 +1055,27 @@ extern "C" size_t Py_UniversalNewlineFread(char* buf, size_t n, FILE* stream, Py
return dst - buf; return dst - buf;
} }
static PyObject* file_isatty(BoxedFile* f) noexcept {
long res;
if (f->f_fp == NULL)
return err_closed();
FILE_BEGIN_ALLOW_THREADS(f)
res = isatty((int)fileno(f->f_fp));
FILE_END_ALLOW_THREADS(f)
return PyBool_FromLong(res);
}
PyDoc_STRVAR(readlines_doc, "readlines([size]) -> list of strings, each a line from the file.\n" PyDoc_STRVAR(readlines_doc, "readlines([size]) -> list of strings, each a line from the file.\n"
"\n" "\n"
"Call readline() repeatedly and return a list of the lines so read.\n" "Call readline() repeatedly and return a list of the lines so read.\n"
"The optional size argument, if given, is an approximate bound on the\n" "The optional size argument, if given, is an approximate bound on the\n"
"total number of bytes in the lines returned."); "total number of bytes in the lines returned.");
PyDoc_STRVAR(isatty_doc, "isatty() -> true or false. True if the file is connected to a tty device.");
PyMethodDef file_methods[] = { PyMethodDef file_methods[] = {
{ "readlines", (PyCFunction)file_readlines, METH_VARARGS, readlines_doc }, { "readlines", (PyCFunction)file_readlines, METH_VARARGS, readlines_doc },
{ "isatty", (PyCFunction)file_isatty, METH_NOARGS, isatty_doc },
}; };
void fileDestructor(Box* b) { void fileDestructor(Box* b) {
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "gc/heap.h" #include "gc/heap.h"
#include "runtime/capi.h" #include "runtime/capi.h"
#include "runtime/classobj.h" #include "runtime/classobj.h"
#include "runtime/dict.h"
#include "runtime/file.h" #include "runtime/file.h"
#include "runtime/float.h" #include "runtime/float.h"
#include "runtime/generator.h" #include "runtime/generator.h"
...@@ -1940,7 +1941,7 @@ extern "C" BoxedInt* hash(Box* obj) { ...@@ -1940,7 +1941,7 @@ extern "C" BoxedInt* hash(Box* obj) {
Box* hash = getclsattr_internal(obj, "__hash__", NULL); Box* hash = getclsattr_internal(obj, "__hash__", NULL);
if (hash == NULL) { if (hash == NULL) {
ASSERT(isUserDefined(obj->cls), "%s.__hash__", getTypeName(obj)); ASSERT(isUserDefined(obj->cls) || obj->cls == function_cls, "%s.__hash__", getTypeName(obj));
// TODO not the best way to handle this... // TODO not the best way to handle this...
return static_cast<BoxedInt*>(boxInt((i64)obj)); return static_cast<BoxedInt*>(boxInt((i64)obj));
} }
...@@ -2693,7 +2694,13 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe ...@@ -2693,7 +2694,13 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe
Box* kwargs Box* kwargs
= getArg(argspec.num_args + argspec.num_keywords + (argspec.has_starargs ? 1 : 0), arg1, arg2, arg3, args); = getArg(argspec.num_args + argspec.num_keywords + (argspec.has_starargs ? 1 : 0), arg1, arg2, arg3, args);
RELEASE_ASSERT(kwargs->cls == dict_cls, "haven't implemented this for non-dicts");
if (!isSubclass(kwargs->cls, dict_cls)) {
BoxedDict* d = new BoxedDict();
dictMerge(d, kwargs);
kwargs = d;
}
assert(isSubclass(kwargs->cls, dict_cls));
BoxedDict* d_kwargs = static_cast<BoxedDict*>(kwargs); BoxedDict* d_kwargs = static_cast<BoxedDict*>(kwargs);
for (auto& p : d_kwargs->d) { for (auto& p : d_kwargs->d) {
......
...@@ -1159,10 +1159,9 @@ Box* objectStr(Box* obj) { ...@@ -1159,10 +1159,9 @@ Box* objectStr(Box* obj) {
} }
static Box* typeName(Box* b, void*) { static Box* typeName(Box* b, void*) {
assert(b->cls == type_cls); RELEASE_ASSERT(isSubclass(b->cls, type_cls), "");
BoxedClass* type = static_cast<BoxedClass*>(b); BoxedClass* type = static_cast<BoxedClass*>(b);
// TODO is this predicate right?
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
BoxedHeapClass* et = static_cast<BoxedHeapClass*>(type); BoxedHeapClass* et = static_cast<BoxedHeapClass*>(type);
return et->ht_name; return et->ht_name;
...@@ -1516,6 +1515,7 @@ void setupRuntime() { ...@@ -1516,6 +1515,7 @@ void setupRuntime() {
setupPyston(); setupPyston();
PyType_Ready(&PyCapsule_Type); PyType_Ready(&PyCapsule_Type);
PyType_Ready(&PyCallIter_Type);
initerrno(); initerrno();
init_sha(); init_sha();
......
# expected: fail
# - not supported yet
class C(object): class C(object):
def __len__(self): def __len__(self):
print "__len__" print "__len__"
...@@ -26,3 +23,20 @@ def f(a, b, c): ...@@ -26,3 +23,20 @@ def f(a, b, c):
print a, b, c print a, b, c
f(**C()) f(**C())
class MyDict(dict):
pass
d = MyDict(a=1, b=2, c=3)
print f(**d)
# Django does this:
class C(object):
pass
c = C()
c.a = 1
c.b = 3
c.c = 7
print f(**c.__dict__)
# no-collect-stats
import sys
sys.exit(None)
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