summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-08-06 16:50:37 (GMT)
committerGuido van Rossum <guido@python.org>2001-08-06 16:50:37 (GMT)
commit0d231eda52dac76dd308f53d14e0dece6285c506 (patch)
tree927482c77022834be372c02e2b7ec255da473867
parent4590049228fc8195ba4c123cc67794a1bfbd29d3 (diff)
downloadcpython-0d231eda52dac76dd308f53d14e0dece6285c506.zip
cpython-0d231eda52dac76dd308f53d14e0dece6285c506.tar.gz
cpython-0d231eda52dac76dd308f53d14e0dece6285c506.tar.bz2
A totally new way to do the __new__ wrapper. This should address the
problem brought up in SF bug #444229.
-rw-r--r--Objects/typeobject.c79
1 files changed, 45 insertions, 34 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 9b7243b..37afb47 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -939,31 +939,6 @@ add_wrappers(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
}
static int
-add_staticmethodwrappers(PyTypeObject *type, struct wrapperbase *base,
- void *wrapped)
-{
- PyObject *dict = type->tp_defined;
- PyObject *sm;
-
- for (; base->name != NULL; base++) {
- PyObject *descr;
- if (PyDict_GetItemString(dict, base->name))
- continue;
- descr = PyDescr_NewWrapper(type->ob_type, base, wrapped);
- if (descr == NULL)
- return -1;
- sm = PyStaticMethod_New(descr);
- Py_DECREF(descr);
- if (sm == NULL)
- return -1;
- if (PyDict_SetItemString(dict, base->name, sm) < 0)
- return -1;
- Py_DECREF(sm);
- }
- return 0;
-}
-
-static int
add_members(PyTypeObject *type, struct memberlist *memb)
{
PyObject *dict = type->tp_defined;
@@ -1197,7 +1172,7 @@ PyType_InitDict(PyTypeObject *type)
}
/* Initialize the base class */
- if (base) {
+ if (base && base->tp_dict == NULL) {
if (PyType_InitDict(base) < 0)
return -1;
}
@@ -1853,19 +1828,56 @@ static struct wrapperbase tab_init[] = {
};
static PyObject *
-wrap_new(PyObject *type, PyObject *args, void *wrapped)
+tp_new_wrapper(PyObject *self, PyObject *args, PyObject *kwds)
{
- newfunc new = (newfunc)wrapped;
- return new((PyTypeObject *)type, args, NULL);
+ PyTypeObject *type, *subtype;
+ PyObject *arg0, *res;
+
+ if (self == NULL || !PyType_Check(self))
+ Py_FatalError("__new__() called with non-type 'self'");
+ type = (PyTypeObject *)self;
+ if (!PyTuple_Check(args) || PyTuple_GET_SIZE(args) < 1) {
+ PyErr_SetString(PyExc_TypeError,
+ "T.__new__(): not enough arguments");
+ return NULL;
+ }
+ arg0 = PyTuple_GET_ITEM(args, 0);
+ if (!PyType_Check(arg0)) {
+ PyErr_SetString(PyExc_TypeError,
+ "T.__new__(S): S is not a type object");
+ return NULL;
+ }
+ subtype = (PyTypeObject *)arg0;
+ if (!PyType_IsSubtype(subtype, type)) {
+ PyErr_SetString(PyExc_TypeError,
+ "T.__new__(S): S is not a subtype of T");
+ return NULL;
+ }
+ args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
+ if (args == NULL)
+ return NULL;
+ res = type->tp_new(subtype, args, kwds);
+ Py_DECREF(args);
+ return res;
}
-static struct wrapperbase tab_new[] = {
- {"__new__", (wrapperfunc)wrap_new,
- "T.__new__() -> an object with type T"},
+static struct PyMethodDef tp_new_methoddef[] = {
+ {"__new__", (PyCFunction)tp_new_wrapper, METH_KEYWORDS,
+ "T.__new__(S, ...) -> a new object with type S, a subtype of T"},
{0}
};
static int
+add_tp_new_wrapper(PyTypeObject *type)
+{
+ PyObject *func = PyCFunction_New(tp_new_methoddef, (PyObject *)type);
+
+ if (func == NULL)
+ return -1;
+ return PyDict_SetItemString(type->tp_defined, "__new__", func);
+}
+
+static int
add_operators(PyTypeObject *type)
{
PySequenceMethods *sq;
@@ -1955,8 +1967,7 @@ add_operators(PyTypeObject *type)
ADD(type->tp_init, tab_init);
if (type->tp_new != NULL)
- add_staticmethodwrappers(type, tab_new,
- (void *)(type->tp_new));
+ add_tp_new_wrapper(type);
return 0;
}