Commit 4d3d6625 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Support os.execvpe

parent 060c05a1
......@@ -284,6 +284,116 @@ extern "C" PyObject* PyObject_CallFunctionObjArgs(PyObject* callable, ...) noexc
return tmp;
}
extern "C" PyObject* PyObject_CallObject(PyObject* obj, PyObject* args) noexcept {
RELEASE_ASSERT(args, ""); // actually it looks like this is allowed to be NULL
RELEASE_ASSERT(args->cls == tuple_cls, "");
// TODO do something like this? not sure if this is safe; will people expect that calling into a known function
// won't end up doing a GIL check?
// threading::GLDemoteRegion _gil_demote;
try {
Box* r = runtimeCall(obj, ArgPassSpec(0, 0, true, false), args, NULL, NULL, NULL, NULL);
return r;
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
static PyObject* call_function_tail(PyObject* callable, PyObject* args) {
PyObject* retval;
if (args == NULL)
return NULL;
if (!PyTuple_Check(args)) {
PyObject* a;
a = PyTuple_New(1);
if (a == NULL) {
Py_DECREF(args);
return NULL;
}
PyTuple_SET_ITEM(a, 0, args);
args = a;
}
retval = PyObject_Call(callable, args, NULL);
Py_DECREF(args);
return retval;
}
extern "C" PyObject* PyObject_CallMethod(PyObject* o, char* name, char* format, ...) noexcept {
Py_FatalError("unimplemented");
}
extern "C" PyObject* _PyObject_CallMethod_SizeT(PyObject* o, char* name, char* format, ...) noexcept {
// TODO it looks like this could be made much more efficient by calling our callattr(), but
// I haven't taken the time to verify that that has the same behavior
va_list va;
PyObject* args;
PyObject* func = NULL;
PyObject* retval = NULL;
if (o == NULL || name == NULL)
return null_error();
func = PyObject_GetAttrString(o, name);
if (func == NULL) {
PyErr_SetString(PyExc_AttributeError, name);
return 0;
}
if (!PyCallable_Check(func)) {
type_error("attribute of type '%.200s' is not callable", func);
goto exit;
}
if (format && *format) {
va_start(va, format);
args = _Py_VaBuildValue_SizeT(format, va);
va_end(va);
} else
args = PyTuple_New(0);
retval = call_function_tail(func, args);
exit:
/* args gets consumed in call_function_tail */
Py_XDECREF(func);
return retval;
}
extern "C" Py_ssize_t PyObject_Size(PyObject* o) noexcept {
try {
return len(o)->n;
} catch (ExcInfo e) {
setCAPIException(e);
return -1;
}
}
extern "C" PyObject* PyObject_GetIter(PyObject* o) noexcept {
try {
return getiter(o);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
extern "C" PyObject* PyObject_Repr(PyObject* obj) noexcept {
try {
return repr(obj);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
static int recursive_issubclass(PyObject* derived, PyObject* cls) noexcept {
int retval;
......@@ -508,4 +618,44 @@ extern "C" PyObject* PySequence_List(PyObject* v) noexcept {
extern "C" PyObject* PyObject_CallFunction(PyObject* callable, char* format, ...) noexcept {
Py_FatalError("unimplemented");
}
extern "C" int PyMapping_Check(PyObject* o) noexcept {
if (o && PyInstance_Check(o))
return PyObject_HasAttrString(o, "__getitem__");
return o && o->cls->tp_as_mapping && o->cls->tp_as_mapping->mp_subscript
&& !(o->cls->tp_as_sequence && o->cls->tp_as_sequence->sq_slice);
}
extern "C" Py_ssize_t PyMapping_Size(PyObject* o) noexcept {
PyMappingMethods* m;
if (o == NULL) {
null_error();
return -1;
}
m = o->cls->tp_as_mapping;
if (m && m->mp_length)
return m->mp_length(o);
type_error("object of type '%.200s' has no len()", o);
return -1;
}
extern "C" int PyMapping_HasKeyString(PyObject* o, char* key) noexcept {
Py_FatalError("unimplemented");
}
extern "C" int PyMapping_HasKey(PyObject* o, PyObject* key) noexcept {
Py_FatalError("unimplemented");
}
extern "C" PyObject* PyMapping_GetItemString(PyObject* o, char* key) noexcept {
Py_FatalError("unimplemented");
}
extern "C" int PyMapping_SetItemString(PyObject* o, char* key, PyObject* v) noexcept {
Py_FatalError("unimplemented");
}
}
......@@ -218,6 +218,10 @@ extern "C" PyObject* Py_VaBuildValue(const char* format, va_list va) noexcept {
return va_build_value(format, va, 0);
}
extern "C" PyObject* _Py_VaBuildValue_SizeT(const char* format, va_list va) noexcept {
return va_build_value(format, va, FLAG_SIZE_T);
}
extern "C" PyObject* _Py_BuildValue_SizeT(const char* fmt, ...) noexcept {
va_list ap;
va_start(ap, fmt);
......
......@@ -606,6 +606,13 @@ class BoxedException : public Box {
public:
HCAttrs attrs;
BoxedException() {}
static Box* __reduce__(Box* self) {
RELEASE_ASSERT(isSubclass(self->cls, BaseException), "");
BoxedException* exc = static_cast<BoxedException*>(self);
return new BoxedTuple({ self->cls, EmptyTuple, makeAttrWrapper(self) });
}
};
Box* exceptionNew2(BoxedClass* cls, Box* message) {
......@@ -865,6 +872,8 @@ public:
return None;
}
static Box* __reduce__(Box* self) { Py_FatalError("unimplemented"); }
static PyObject* __str__(BoxedEnvironmentError* self) noexcept {
PyObject* rtnval = NULL;
......
......@@ -154,57 +154,6 @@ extern "C" void PyObject_Free(void* p) noexcept {
ASSERT(0, "I think this is good enough but I'm not sure; should test");
}
extern "C" PyObject* PyObject_CallObject(PyObject* obj, PyObject* args) noexcept {
RELEASE_ASSERT(args, ""); // actually it looks like this is allowed to be NULL
RELEASE_ASSERT(args->cls == tuple_cls, "");
// TODO do something like this? not sure if this is safe; will people expect that calling into a known function
// won't end up doing a GIL check?
// threading::GLDemoteRegion _gil_demote;
try {
Box* r = runtimeCall(obj, ArgPassSpec(0, 0, true, false), args, NULL, NULL, NULL, NULL);
return r;
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
extern "C" PyObject* PyObject_CallMethod(PyObject* o, char* name, char* format, ...) noexcept {
Py_FatalError("unimplemented");
}
extern "C" PyObject* _PyObject_CallMethod_SizeT(PyObject* o, char* name, char* format, ...) noexcept {
Py_FatalError("unimplemented");
}
extern "C" Py_ssize_t PyObject_Size(PyObject* o) noexcept {
try {
return len(o)->n;
} catch (ExcInfo e) {
setCAPIException(e);
return -1;
}
}
extern "C" PyObject* PyObject_GetIter(PyObject* o) noexcept {
try {
return getiter(o);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
extern "C" PyObject* PyObject_Repr(PyObject* obj) noexcept {
try {
return repr(obj);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
extern "C" PyObject* PyObject_Format(PyObject* obj, PyObject* format_spec) noexcept {
PyObject* empty = NULL;
PyObject* result = NULL;
......
......@@ -535,30 +535,6 @@ extern "C" Box* dictInit(BoxedDict* self, BoxedTuple* args, BoxedDict* kwargs) {
return None;
}
extern "C" int PyMapping_Check(PyObject* o) noexcept {
Py_FatalError("unimplemented");
}
extern "C" Py_ssize_t PyMapping_Size(PyObject* o) noexcept {
Py_FatalError("unimplemented");
}
extern "C" int PyMapping_HasKeyString(PyObject* o, char* key) noexcept {
Py_FatalError("unimplemented");
}
extern "C" int PyMapping_HasKey(PyObject* o, PyObject* key) noexcept {
Py_FatalError("unimplemented");
}
extern "C" PyObject* PyMapping_GetItemString(PyObject* o, char* key) noexcept {
Py_FatalError("unimplemented");
}
extern "C" int PyMapping_SetItemString(PyObject* o, char* key, PyObject* v) noexcept {
Py_FatalError("unimplemented");
}
BoxedClass* dict_iterator_cls = NULL;
extern "C" void dictIteratorGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
......
......@@ -687,6 +687,11 @@ extern "C" Box* sliceNew(Box* cls, Box* start, Box* stop, Box** args) {
return createSlice(start, stop, step);
}
static Box* instancemethodCall(BoxedInstanceMethod* self, Box* args, Box* kwargs) {
RELEASE_ASSERT(self->cls == instancemethod_cls, "");
Py_FatalError("unimplemented");
}
Box* instancemethodGet(BoxedInstanceMethod* self, Box* obj, Box* type) {
RELEASE_ASSERT(self->cls == instancemethod_cls, "");
......@@ -1200,6 +1205,8 @@ void setupRuntime() {
instancemethod_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)instancemethodEq, UNKNOWN, 2)));
instancemethod_cls->giveAttr(
"__get__", new BoxedFunction(boxRTFunction((void*)instancemethodGet, UNKNOWN, 3, 0, false, false)));
instancemethod_cls->giveAttr(
"__call__", new BoxedFunction(boxRTFunction((void*)instancemethodCall, UNKNOWN, 1, 0, true, true)));
instancemethod_cls->giveAttr(
"im_func", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedInstanceMethod, func)));
instancemethod_cls->giveAttr(
......
# no-collect-stats
import os
os.execvpe("echo", ["it", "worked!"], {})
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