Commit 9935ce51 authored by Marius Wachtler's avatar Marius Wachtler

Merge pull request #1028 from rudi-c/tp_new

Fixes for tp_new for C extensions
parents c9268664 79eea221
......@@ -926,6 +926,22 @@ template <ExceptionStyle S> Box* floatNew(BoxedClass* _cls, Box* a) noexcept(S =
return new (cls) BoxedFloat(f->d);
}
// Roughly analogous to CPython's float_new.
// The arguments need to be unpacked from args and kwds.
static Box* floatNewPacked(BoxedClass* type, Box* args, Box* kwds) noexcept {
PyObject* x = False;
static char* kwlist[2] = { NULL, NULL };
kwlist[0] = const_cast<char*>("x");
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:float", kwlist, &x))
return NULL;
if (x == NULL)
return floatNew<CAPI>(type, None);
else
return floatNew<CAPI>(type, x);
}
PyObject* float_str_or_repr(double v, int precision, char format_code) {
PyObject* result;
char* buf = PyOS_double_to_string(v, format_code, precision, Py_DTSF_ADD_DOT_0, NULL);
......@@ -1699,6 +1715,7 @@ void setupFloat() {
float_cls->tp_str = float_str;
float_cls->tp_as_number->nb_power = float_pow;
float_cls->tp_new = (newfunc)floatNewPacked;
}
void teardownFloat() {
......
......@@ -1247,6 +1247,24 @@ template <ExceptionStyle S> Box* intNew(Box* _cls, Box* val, Box* base) noexcept
return new (cls) BoxedInt(n->n);
}
// Roughly analogous to CPython's int_new.
// The arguments need to be unpacked from args and kwds.
static Box* intNewPacked(BoxedClass* type, Box* args, Box* kwds) noexcept {
PyObject* x = NULL;
int base = -909;
static char* kwlist[3] = { NULL, NULL, NULL };
kwlist[0] = const_cast<char*>("x");
kwlist[1] = const_cast<char*>("base");
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist, &x, &base))
return NULL;
if (base == -909)
return intNew<CAPI>(type, x, NULL);
else
return intNew<CAPI>(type, x, boxInt(base));
}
static const unsigned char BitLengthTable[32]
= { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
......@@ -1489,6 +1507,7 @@ void setupInt() {
int_cls->freeze();
int_cls->tp_repr = (reprfunc)int_to_decimal_string;
int_cls->tp_new = (newfunc)intNewPacked;
}
void teardownInt() {
......
......@@ -1632,11 +1632,11 @@ extern "C" Box* strNonzero(BoxedString* self) {
return boxBool(self->size() != 0);
}
extern "C" Box* strNew(BoxedClass* cls, Box* obj) {
template <ExceptionStyle S> Box* strNew(BoxedClass* cls, Box* obj) noexcept(S == CAPI) {
assert(isSubclass(cls, str_cls));
if (cls != str_cls) {
Box* tmp = strNew(str_cls, obj);
Box* tmp = strNew<S>(str_cls, obj);
assert(PyString_Check(tmp));
BoxedString* tmp_s = static_cast<BoxedString*>(tmp);
......@@ -1644,10 +1644,30 @@ extern "C" Box* strNew(BoxedClass* cls, Box* obj) {
}
Box* r = PyObject_Str(obj);
if (!r)
throwCAPIException();
assert(PyString_Check(r));
return r;
if (S == CAPI)
return r;
else {
if (!r)
throwCAPIException();
assert(PyString_Check(r));
return r;
}
}
// Roughly analogous to CPython's string_new.
// The arguments need to be unpacked from args and kwds.
static Box* strNewPacked(BoxedClass* type, Box* args, Box* kwds) noexcept {
PyObject* x = NULL;
static char* kwlist[2] = { NULL, NULL };
kwlist[0] = const_cast<char*>("object");
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:str", kwlist, &x))
return NULL;
if (x == NULL)
return PyString_FromString("");
return strNew<CAPI>(type, x);
}
extern "C" Box* basestringNew(BoxedClass* cls, Box* args, Box* kwargs) {
......@@ -2901,8 +2921,9 @@ void setupStr() {
str_cls->giveAttr(md.ml_name, new BoxedMethodDescriptor(&md, str_cls));
}
str_cls->giveAttr("__new__", new BoxedFunction(FunctionMetadata::create((void*)strNew, UNKNOWN, 2, false, false),
{ EmptyString }));
auto str_new = FunctionMetadata::create((void*)strNew<CXX>, UNKNOWN, 2, false, false, ParamNames::empty(), CXX);
str_new->addVersion((void*)strNew<CAPI>, UNKNOWN, CAPI);
str_cls->giveAttr("__new__", new BoxedFunction(str_new, { EmptyString }));
add_operators(str_cls);
str_cls->freeze();
......@@ -2916,6 +2937,7 @@ void setupStr() {
str_cls->tp_as_sequence->sq_item = (ssizeargfunc)string_item;
str_cls->tp_as_sequence->sq_slice = str_slice;
str_cls->tp_as_sequence->sq_contains = (objobjproc)string_contains;
str_cls->tp_new = (newfunc)strNewPacked;
basestring_cls->giveAttr("__doc__",
boxString("Type basestring cannot be instantiated; it is the base for str and unicode."));
......
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